blob: 90e54e82e759033893f657f4caacf6f57c01a356 [file] [log] [blame]
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001/*
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#pragma once
17
James Feist35e257a2020-06-05 13:30:51 -070018#include "health.hpp"
19
John Edward Broadbent7e860f12021-04-08 15:57:16 -070020#include <app.hpp>
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +020021#include <boost/container/flat_map.hpp>
Ed Tanoused398212021-06-09 17:05:54 -070022#include <registries/privilege_registry.hpp>
Gunnar Mills116bcc52020-10-14 15:23:42 -050023#include <utils/collection.hpp>
Ed Tanousf201ffb2021-10-09 14:49:28 -070024#include <utils/hex_utils.hpp>
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +020025#include <utils/json_utils.hpp>
26
27namespace redfish
28{
29
James Feistc50e7c62020-07-27 15:39:36 -070030using DimmProperty =
31 std::variant<std::string, std::vector<uint32_t>, std::vector<uint16_t>,
32 uint64_t, uint32_t, uint16_t, uint8_t, bool>;
33
34using DimmProperties = boost::container::flat_map<std::string, DimmProperty>;
35
Gunnar Mills313efb12020-10-26 16:05:08 -050036inline std::string translateMemoryTypeToRedfish(const std::string& memoryType)
37{
38 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR")
39 {
40 return "DDR";
41 }
42 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR2")
43 {
44 return "DDR2";
45 }
46 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR3")
47 {
48 return "DDR3";
49 }
50 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR4")
51 {
52 return "DDR4";
53 }
54 if (memoryType ==
55 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR4E_SDRAM")
56 {
57 return "DDR4E_SDRAM";
58 }
Mansi Joshi11a2f0f2021-07-19 14:33:27 +053059 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR5")
60 {
61 return "DDR5";
62 }
Gunnar Mills313efb12020-10-26 16:05:08 -050063 if (memoryType ==
64 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.LPDDR4_SDRAM")
65 {
66 return "LPDDR4_SDRAM";
67 }
68 if (memoryType ==
69 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.LPDDR3_SDRAM")
70 {
71 return "LPDDR3_SDRAM";
72 }
73 if (memoryType ==
74 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR2_SDRAM_FB_DIMM")
75 {
76 return "DDR2_SDRAM_FB_DIMM";
77 }
George Liu0fda0f12021-11-16 10:06:17 +080078 if (memoryType ==
79 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR2_SDRAM_FB_DIMM_PROB")
Gunnar Mills313efb12020-10-26 16:05:08 -050080 {
81 return "DDR2_SDRAM_FB_DIMM_PROBE";
82 }
83 if (memoryType ==
84 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR_SGRAM")
85 {
86 return "DDR_SGRAM";
87 }
88 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.ROM")
89 {
90 return "ROM";
91 }
92 if (memoryType ==
93 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.SDRAM")
94 {
95 return "SDRAM";
96 }
97 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.EDO")
98 {
99 return "EDO";
100 }
101 if (memoryType ==
102 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.FastPageMode")
103 {
104 return "FastPageMode";
105 }
106 if (memoryType ==
107 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.PipelinedNibble")
108 {
109 return "PipelinedNibble";
110 }
111 if (memoryType ==
112 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.Logical")
113 {
114 return "Logical";
115 }
116 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.HBM")
117 {
118 return "HBM";
119 }
120 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.HBM2")
121 {
122 return "HBM2";
123 }
124 // This is values like Other or Unknown
125 // Also D-Bus values:
126 // DRAM
127 // EDRAM
128 // VRAM
129 // SRAM
130 // RAM
131 // FLASH
132 // EEPROM
133 // FEPROM
134 // EPROM
135 // CDRAM
136 // ThreeDRAM
137 // RDRAM
138 // FBD2
139 // LPDDR_SDRAM
140 // LPDDR2_SDRAM
Mansi Joshi11a2f0f2021-07-19 14:33:27 +0530141 // LPDDR5_SDRAM
Gunnar Mills313efb12020-10-26 16:05:08 -0500142 return "";
143}
144
zhanghch058d1b46d2021-04-01 11:18:24 +0800145inline void dimmPropToHex(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Ed Tanousb5a76932020-09-29 16:16:58 -0700146 const char* key,
Ed Tanous80789c82020-08-19 09:19:09 -0700147 const std::pair<std::string, DimmProperty>& property)
James Feistc50e7c62020-07-27 15:39:36 -0700148{
149 const uint16_t* value = std::get_if<uint16_t>(&property.second);
150 if (value == nullptr)
151 {
152 messages::internalError(aResp->res);
153 BMCWEB_LOG_DEBUG << "Invalid property type for " << property.first;
154 return;
155 }
156
Ed Tanousf201ffb2021-10-09 14:49:28 -0700157 aResp->res.jsonValue[key] = "0x" + intToHexString(*value);
James Feistc50e7c62020-07-27 15:39:36 -0700158}
159
zhanghch058d1b46d2021-04-01 11:18:24 +0800160inline void getPersistentMemoryProperties(
161 const std::shared_ptr<bmcweb::AsyncResp>& aResp,
162 const DimmProperties& properties)
James Feistc50e7c62020-07-27 15:39:36 -0700163{
164 for (const auto& property : properties)
165 {
166 if (property.first == "ModuleManufacturerID")
167 {
168 dimmPropToHex(aResp, "ModuleManufacturerID", property);
169 }
170 else if (property.first == "ModuleProductID")
171 {
172 dimmPropToHex(aResp, "ModuleProductID", property);
173 }
174 else if (property.first == "SubsystemVendorID")
175 {
176 dimmPropToHex(aResp, "MemorySubsystemControllerManufacturerID",
177 property);
178 }
179 else if (property.first == "SubsystemDeviceID")
180 {
181 dimmPropToHex(aResp, "MemorySubsystemControllerProductID",
182 property);
183 }
184 else if (property.first == "VolatileRegionSizeLimitInKiB")
185 {
186 const uint64_t* value = std::get_if<uint64_t>(&property.second);
187
188 if (value == nullptr)
189 {
190 messages::internalError(aResp->res);
George Liu0fda0f12021-11-16 10:06:17 +0800191 BMCWEB_LOG_DEBUG
192 << "Invalid property type for VolatileRegionSizeLimitKiB";
Chicago Duan601af5e2021-04-15 16:59:25 +0800193 return;
James Feistc50e7c62020-07-27 15:39:36 -0700194 }
195 aResp->res.jsonValue["VolatileRegionSizeLimitMiB"] = (*value) >> 10;
196 }
197 else if (property.first == "PmRegionSizeLimitInKiB")
198 {
199 const uint64_t* value = std::get_if<uint64_t>(&property.second);
200
201 if (value == nullptr)
202 {
203 messages::internalError(aResp->res);
204 BMCWEB_LOG_DEBUG
205 << "Invalid property type for PmRegioSizeLimitKiB";
Chicago Duan601af5e2021-04-15 16:59:25 +0800206 return;
James Feistc50e7c62020-07-27 15:39:36 -0700207 }
208 aResp->res.jsonValue["PersistentRegionSizeLimitMiB"] =
209 (*value) >> 10;
210 }
211 else if (property.first == "VolatileSizeInKiB")
212 {
213 const uint64_t* value = std::get_if<uint64_t>(&property.second);
214
215 if (value == nullptr)
216 {
217 messages::internalError(aResp->res);
218 BMCWEB_LOG_DEBUG
219 << "Invalid property type for VolatileSizeInKiB";
Chicago Duan601af5e2021-04-15 16:59:25 +0800220 return;
James Feistc50e7c62020-07-27 15:39:36 -0700221 }
222 aResp->res.jsonValue["VolatileSizeMiB"] = (*value) >> 10;
223 }
224 else if (property.first == "PmSizeInKiB")
225 {
226 const uint64_t* value = std::get_if<uint64_t>(&property.second);
227 if (value == nullptr)
228 {
229 messages::internalError(aResp->res);
230 BMCWEB_LOG_DEBUG << "Invalid property type for PmSizeInKiB";
Chicago Duan601af5e2021-04-15 16:59:25 +0800231 return;
James Feistc50e7c62020-07-27 15:39:36 -0700232 }
233 aResp->res.jsonValue["NonVolatileSizeMiB"] = (*value) >> 10;
234 }
235 else if (property.first == "CacheSizeInKB")
236 {
237 const uint64_t* value = std::get_if<uint64_t>(&property.second);
238 if (value == nullptr)
239 {
240 messages::internalError(aResp->res);
241 BMCWEB_LOG_DEBUG << "Invalid property type for CacheSizeInKB";
Chicago Duan601af5e2021-04-15 16:59:25 +0800242 return;
James Feistc50e7c62020-07-27 15:39:36 -0700243 }
244 aResp->res.jsonValue["CacheSizeMiB"] = (*value >> 10);
245 }
246
247 else if (property.first == "VoltaileRegionMaxSizeInKib")
248 {
249 const uint64_t* value = std::get_if<uint64_t>(&property.second);
250
251 if (value == nullptr)
252 {
253 messages::internalError(aResp->res);
George Liu0fda0f12021-11-16 10:06:17 +0800254 BMCWEB_LOG_DEBUG
255 << "Invalid property type for VolatileRegionMaxSizeInKib";
Chicago Duan601af5e2021-04-15 16:59:25 +0800256 return;
James Feistc50e7c62020-07-27 15:39:36 -0700257 }
258 aResp->res.jsonValue["VolatileRegionSizeMaxMiB"] = (*value) >> 10;
259 }
260 else if (property.first == "PmRegionMaxSizeInKiB")
261 {
262 const uint64_t* value = std::get_if<uint64_t>(&property.second);
263
264 if (value == nullptr)
265 {
266 messages::internalError(aResp->res);
267 BMCWEB_LOG_DEBUG
268 << "Invalid property type for PmRegionMaxSizeInKiB";
Chicago Duan601af5e2021-04-15 16:59:25 +0800269 return;
James Feistc50e7c62020-07-27 15:39:36 -0700270 }
271 aResp->res.jsonValue["PersistentRegionSizeMaxMiB"] = (*value) >> 10;
272 }
273 else if (property.first == "AllocationIncrementInKiB")
274 {
275 const uint64_t* value = std::get_if<uint64_t>(&property.second);
276
277 if (value == nullptr)
278 {
279 messages::internalError(aResp->res);
George Liu0fda0f12021-11-16 10:06:17 +0800280 BMCWEB_LOG_DEBUG
281 << "Invalid property type for AllocationIncrementInKiB";
Chicago Duan601af5e2021-04-15 16:59:25 +0800282 return;
James Feistc50e7c62020-07-27 15:39:36 -0700283 }
284 aResp->res.jsonValue["AllocationIncrementMiB"] = (*value) >> 10;
285 }
286 else if (property.first == "AllocationAlignmentInKiB")
287 {
288 const uint64_t* value = std::get_if<uint64_t>(&property.second);
289
290 if (value == nullptr)
291 {
292 messages::internalError(aResp->res);
George Liu0fda0f12021-11-16 10:06:17 +0800293 BMCWEB_LOG_DEBUG
294 << "Invalid property type for AllocationAlignmentInKiB";
Chicago Duan601af5e2021-04-15 16:59:25 +0800295 return;
James Feistc50e7c62020-07-27 15:39:36 -0700296 }
297 aResp->res.jsonValue["AllocationAlignmentMiB"] = (*value) >> 10;
298 }
299 else if (property.first == "VolatileRegionNumberLimit")
300 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700301 const uint64_t* value = std::get_if<uint64_t>(&property.second);
302 if (value == nullptr)
303 {
304 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +0800305 return;
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700306 }
307 aResp->res.jsonValue["VolatileRegionNumberLimit"] = *value;
James Feistc50e7c62020-07-27 15:39:36 -0700308 }
309 else if (property.first == "PmRegionNumberLimit")
310 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700311 const uint64_t* value = std::get_if<uint64_t>(&property.second);
312 if (value == nullptr)
313 {
314 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +0800315 return;
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700316 }
317 aResp->res.jsonValue["PersistentRegionNumberLimit"] = *value;
James Feistc50e7c62020-07-27 15:39:36 -0700318 }
319 else if (property.first == "SpareDeviceCount")
320 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700321 const uint64_t* value = std::get_if<uint64_t>(&property.second);
322 if (value == nullptr)
323 {
324 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +0800325 return;
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700326 }
327 aResp->res.jsonValue["SpareDeviceCount"] = *value;
James Feistc50e7c62020-07-27 15:39:36 -0700328 }
329 else if (property.first == "IsSpareDeviceInUse")
330 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700331 const bool* value = std::get_if<bool>(&property.second);
332 if (value == nullptr)
333 {
334 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +0800335 return;
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700336 }
337 aResp->res.jsonValue["IsSpareDeviceEnabled"] = *value;
James Feistc50e7c62020-07-27 15:39:36 -0700338 }
339 else if (property.first == "IsRankSpareEnabled")
340 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700341 const bool* value = std::get_if<bool>(&property.second);
342 if (value == nullptr)
343 {
344 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +0800345 return;
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700346 }
347 aResp->res.jsonValue["IsRankSpareEnabled"] = *value;
James Feistc50e7c62020-07-27 15:39:36 -0700348 }
349 else if (property.first == "MaxAveragePowerLimitmW")
350 {
351 const auto* value =
352 std::get_if<std::vector<uint32_t>>(&property.second);
353 if (value == nullptr)
354 {
355 messages::internalError(aResp->res);
George Liu0fda0f12021-11-16 10:06:17 +0800356 BMCWEB_LOG_DEBUG
357 << "Invalid property type for MaxAveragePowerLimitmW";
Chicago Duan601af5e2021-04-15 16:59:25 +0800358 return;
James Feistc50e7c62020-07-27 15:39:36 -0700359 }
360 aResp->res.jsonValue["MaxTDPMilliWatts"] = *value;
361 }
James Feistc50e7c62020-07-27 15:39:36 -0700362 else if (property.first == "ConfigurationLocked")
363 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700364 const bool* value = std::get_if<bool>(&property.second);
365 if (value == nullptr)
366 {
367 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +0800368 return;
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700369 }
370 aResp->res.jsonValue["ConfigurationLocked"] = *value;
James Feistc50e7c62020-07-27 15:39:36 -0700371 }
372 else if (property.first == "AllowedMemoryModes")
373 {
374 const std::string* value =
375 std::get_if<std::string>(&property.second);
376 if (value == nullptr)
377 {
378 messages::internalError(aResp->res);
379 BMCWEB_LOG_DEBUG << "Invalid property type for FormFactor";
Chicago Duan601af5e2021-04-15 16:59:25 +0800380 return;
James Feistc50e7c62020-07-27 15:39:36 -0700381 }
382 constexpr const std::array<const char*, 3> values{"Volatile",
383 "PMEM", "Block"};
384
385 for (const char* v : values)
386 {
387 if (boost::ends_with(*value, v))
388 {
389 aResp->res.jsonValue["OperatingMemoryModes "] = v;
390 break;
391 }
392 }
393 }
394 else if (property.first == "MemoryMedia")
395 {
396 const std::string* value =
397 std::get_if<std::string>(&property.second);
398 if (value == nullptr)
399 {
400 messages::internalError(aResp->res);
401 BMCWEB_LOG_DEBUG << "Invalid property type for MemoryMedia";
Chicago Duan601af5e2021-04-15 16:59:25 +0800402 return;
James Feistc50e7c62020-07-27 15:39:36 -0700403 }
404 constexpr const std::array<const char*, 3> values{"DRAM", "NAND",
405 "Intel3DXPoint"};
406
407 for (const char* v : values)
408 {
409 if (boost::ends_with(*value, v))
410 {
411 aResp->res.jsonValue["MemoryMedia"] = v;
412 break;
413 }
414 }
415 }
James Feistc50e7c62020-07-27 15:39:36 -0700416 // PersistantMemory.SecurityCapabilites interface
417 else if (property.first == "ConfigurationLockCapable" ||
418 property.first == "DataLockCapable" ||
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700419 property.first == "PassphraseCapable")
420 {
421 const bool* value = std::get_if<bool>(&property.second);
422 if (value == nullptr)
423 {
424 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +0800425 return;
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700426 }
427 aResp->res.jsonValue["SecurityCapabilities"][property.first] =
428 *value;
429 }
430 else if (property.first == "MaxPassphraseCount" ||
James Feistc50e7c62020-07-27 15:39:36 -0700431 property.first == "PassphraseLockLimit")
432 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700433 const uint64_t* value = std::get_if<uint64_t>(&property.second);
434 if (value == nullptr)
435 {
436 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +0800437 return;
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700438 }
James Feistc50e7c62020-07-27 15:39:36 -0700439 aResp->res.jsonValue["SecurityCapabilities"][property.first] =
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700440 *value;
James Feistc50e7c62020-07-27 15:39:36 -0700441 }
442 }
443}
444
zhanghch058d1b46d2021-04-01 11:18:24 +0800445inline void getDimmDataByService(std::shared_ptr<bmcweb::AsyncResp> aResp,
Ed Tanous80789c82020-08-19 09:19:09 -0700446 const std::string& dimmId,
447 const std::string& service,
448 const std::string& objPath)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200449{
James Feist35e257a2020-06-05 13:30:51 -0700450 auto health = std::make_shared<HealthPopulate>(aResp);
451 health->selfPath = objPath;
452 health->populate();
453
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200454 BMCWEB_LOG_DEBUG << "Get available system components.";
455 crow::connections::systemBus->async_method_call(
James Feistc50e7c62020-07-27 15:39:36 -0700456 [dimmId, aResp{std::move(aResp)}](const boost::system::error_code ec,
457 const DimmProperties& properties) {
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200458 if (ec)
459 {
460 BMCWEB_LOG_DEBUG << "DBUS response error";
461 messages::internalError(aResp->res);
462
463 return;
464 }
465 aResp->res.jsonValue["Id"] = dimmId;
466 aResp->res.jsonValue["Name"] = "DIMM Slot";
467
468 const auto memorySizeProperty = properties.find("MemorySizeInKB");
Gunnar Millsaceb7fc2018-12-10 15:17:20 -0600469 if (memorySizeProperty != properties.end())
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200470 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500471 const uint32_t* memorySize =
Ed Tanousabf2add2019-01-22 16:40:12 -0800472 std::get_if<uint32_t>(&memorySizeProperty->second);
Gunnar Millsaceb7fc2018-12-10 15:17:20 -0600473 if (memorySize == nullptr)
474 {
475 // Important property not in desired type
476 messages::internalError(aResp->res);
Gunnar Millsaceb7fc2018-12-10 15:17:20 -0600477 return;
478 }
479 aResp->res.jsonValue["CapacityMiB"] = (*memorySize >> 10);
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200480 }
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200481 aResp->res.jsonValue["Status"]["State"] = "Enabled";
482 aResp->res.jsonValue["Status"]["Health"] = "OK";
483
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500484 for (const auto& property : properties)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200485 {
486 if (property.first == "MemoryDataWidth")
487 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700488 const uint16_t* value =
489 std::get_if<uint16_t>(&property.second);
490 if (value == nullptr)
491 {
492 continue;
493 }
494 aResp->res.jsonValue["DataWidthBits"] = *value;
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200495 }
Manojkiran Eda7e236ca2019-06-25 23:06:32 +0530496 else if (property.first == "PartNumber")
497 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700498 const std::string* value =
499 std::get_if<std::string>(&property.second);
500 if (value == nullptr)
501 {
502 continue;
503 }
504 aResp->res.jsonValue["PartNumber"] = *value;
Manojkiran Eda7e236ca2019-06-25 23:06:32 +0530505 }
506 else if (property.first == "SerialNumber")
507 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700508 const std::string* value =
509 std::get_if<std::string>(&property.second);
510 if (value == nullptr)
511 {
512 continue;
513 }
514 aResp->res.jsonValue["SerialNumber"] = *value;
Manojkiran Eda7e236ca2019-06-25 23:06:32 +0530515 }
516 else if (property.first == "Manufacturer")
517 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700518 const std::string* value =
519 std::get_if<std::string>(&property.second);
520 if (value == nullptr)
521 {
522 continue;
523 }
524 aResp->res.jsonValue["Manufacturer"] = *value;
Manojkiran Eda7e236ca2019-06-25 23:06:32 +0530525 }
James Feistc50e7c62020-07-27 15:39:36 -0700526 else if (property.first == "RevisionCode")
527 {
528 const uint16_t* value =
529 std::get_if<uint16_t>(&property.second);
530
531 if (value == nullptr)
532 {
533 messages::internalError(aResp->res);
534 BMCWEB_LOG_DEBUG
535 << "Invalid property type for RevisionCode";
Chicago Duan601af5e2021-04-15 16:59:25 +0800536 return;
James Feistc50e7c62020-07-27 15:39:36 -0700537 }
538 aResp->res.jsonValue["FirmwareRevision"] =
539 std::to_string(*value);
540 }
Joshi-Mansi9a128eb2021-03-19 03:30:17 +0530541 else if (property.first == "Present")
542 {
543 const bool* value = std::get_if<bool>(&property.second);
544 if (value == nullptr)
545 {
546 messages::internalError(aResp->res);
547 BMCWEB_LOG_DEBUG
548 << "Invalid property type for Dimm Presence";
549 return;
550 }
551 if (*value == false)
552 {
553 aResp->res.jsonValue["Status"]["State"] = "Absent";
554 }
555 }
James Feistc50e7c62020-07-27 15:39:36 -0700556 else if (property.first == "MemoryTotalWidth")
557 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700558 const uint16_t* value =
559 std::get_if<uint16_t>(&property.second);
560 if (value == nullptr)
561 {
562 continue;
563 }
564 aResp->res.jsonValue["BusWidthBits"] = *value;
James Feistc50e7c62020-07-27 15:39:36 -0700565 }
566 else if (property.first == "ECC")
567 {
568 const std::string* value =
569 std::get_if<std::string>(&property.second);
570 if (value == nullptr)
571 {
572 messages::internalError(aResp->res);
573 BMCWEB_LOG_DEBUG << "Invalid property type for ECC";
Chicago Duan601af5e2021-04-15 16:59:25 +0800574 return;
James Feistc50e7c62020-07-27 15:39:36 -0700575 }
576 constexpr const std::array<const char*, 4> values{
577 "NoECC", "SingleBitECC", "MultiBitECC",
578 "AddressParity"};
579
580 for (const char* v : values)
581 {
582 if (boost::ends_with(*value, v))
583 {
584 aResp->res.jsonValue["ErrorCorrection"] = v;
585 break;
586 }
587 }
588 }
589 else if (property.first == "FormFactor")
590 {
591 const std::string* value =
592 std::get_if<std::string>(&property.second);
593 if (value == nullptr)
594 {
595 messages::internalError(aResp->res);
596 BMCWEB_LOG_DEBUG
597 << "Invalid property type for FormFactor";
Chicago Duan601af5e2021-04-15 16:59:25 +0800598 return;
James Feistc50e7c62020-07-27 15:39:36 -0700599 }
600 constexpr const std::array<const char*, 11> values{
601 "RDIMM", "UDIMM", "SO_DIMM",
602 "LRDIMM", "Mini_RDIMM", "Mini_UDIMM",
603 "SO_RDIMM_72b", "SO_UDIMM_72b", "SO_DIMM_16b",
604 "SO_DIMM_32b", "Die"};
605
606 for (const char* v : values)
607 {
608 if (boost::ends_with(*value, v))
609 {
610 aResp->res.jsonValue["BaseModuleType"] = v;
611 break;
612 }
613 }
614 }
615 else if (property.first == "AllowedSpeedsMT")
616 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700617 const std::vector<uint16_t>* value =
618 std::get_if<std::vector<uint16_t>>(&property.second);
619 if (value == nullptr)
620 {
621 continue;
622 }
623 nlohmann::json& jValue =
624 aResp->res.jsonValue["AllowedSpeedsMHz"];
625 jValue = nlohmann::json::array();
626 for (uint16_t subVal : *value)
627 {
628 jValue.push_back(subVal);
629 }
James Feistc50e7c62020-07-27 15:39:36 -0700630 }
631 else if (property.first == "MemoryAttributes")
632 {
633 const uint8_t* value =
634 std::get_if<uint8_t>(&property.second);
635
636 if (value == nullptr)
637 {
638 messages::internalError(aResp->res);
639 BMCWEB_LOG_DEBUG
640 << "Invalid property type for MemoryAttributes";
Chicago Duan601af5e2021-04-15 16:59:25 +0800641 return;
James Feistc50e7c62020-07-27 15:39:36 -0700642 }
643 aResp->res.jsonValue["RankCount"] =
644 static_cast<uint64_t>(*value);
645 }
646 else if (property.first == "MemoryConfiguredSpeedInMhz")
647 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700648 const uint16_t* value =
649 std::get_if<uint16_t>(&property.second);
650 if (value == nullptr)
651 {
652 continue;
653 }
654 aResp->res.jsonValue["OperatingSpeedMhz"] = *value;
James Feistc50e7c62020-07-27 15:39:36 -0700655 }
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200656 else if (property.first == "MemoryType")
657 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500658 const auto* value =
Ed Tanousabf2add2019-01-22 16:40:12 -0800659 std::get_if<std::string>(&property.second);
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200660 if (value != nullptr)
661 {
Gunnar Mills313efb12020-10-26 16:05:08 -0500662 std::string memoryDeviceType =
663 translateMemoryTypeToRedfish(*value);
664 // Values like "Unknown" or "Other" will return empty
665 // so just leave off
666 if (!memoryDeviceType.empty())
James Feistc50e7c62020-07-27 15:39:36 -0700667 {
Gunnar Mills313efb12020-10-26 16:05:08 -0500668 aResp->res.jsonValue["MemoryDeviceType"] =
669 memoryDeviceType;
James Feistc50e7c62020-07-27 15:39:36 -0700670 }
James Feistc50e7c62020-07-27 15:39:36 -0700671 if (value->find("DDR") != std::string::npos)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200672 {
673 aResp->res.jsonValue["MemoryType"] = "DRAM";
674 }
James Feistc50e7c62020-07-27 15:39:36 -0700675 else if (boost::ends_with(*value, "Logical"))
676 {
677 aResp->res.jsonValue["MemoryType"] = "IntelOptane";
678 }
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200679 }
680 }
James Feistc50e7c62020-07-27 15:39:36 -0700681 // memory location interface
682 else if (property.first == "Channel" ||
683 property.first == "MemoryController" ||
684 property.first == "Slot" || property.first == "Socket")
685 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700686 const std::string* value =
687 std::get_if<std::string>(&property.second);
688 if (value == nullptr)
689 {
690 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +0800691 return;
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700692 }
James Feistc50e7c62020-07-27 15:39:36 -0700693 aResp->res.jsonValue["MemoryLocation"][property.first] =
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700694 *value;
James Feistc50e7c62020-07-27 15:39:36 -0700695 }
SunnySrivastava1984ee135e22020-12-15 12:42:19 -0600696 else if (property.first == "SparePartNumber")
697 {
698 const std::string* value =
699 std::get_if<std::string>(&property.second);
700 if (value == nullptr)
701 {
702 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +0800703 return;
SunnySrivastava1984ee135e22020-12-15 12:42:19 -0600704 }
705 aResp->res.jsonValue["SparePartNumber"] = *value;
706 }
707 else if (property.first == "Model")
708 {
709 const std::string* value =
710 std::get_if<std::string>(&property.second);
711 if (value == nullptr)
712 {
713 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +0800714 return;
SunnySrivastava1984ee135e22020-12-15 12:42:19 -0600715 }
716 aResp->res.jsonValue["Model"] = *value;
717 }
718 else if (property.first == "LocationCode")
719 {
720 const std::string* value =
721 std::get_if<std::string>(&property.second);
722 if (value == nullptr)
723 {
724 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +0800725 return;
SunnySrivastava1984ee135e22020-12-15 12:42:19 -0600726 }
727 aResp->res
728 .jsonValue["Location"]["PartLocation"]["ServiceLabel"] =
729 *value;
730 }
James Feistc50e7c62020-07-27 15:39:36 -0700731 else
732 {
733 getPersistentMemoryProperties(aResp, properties);
734 }
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200735 }
736 },
737 service, objPath, "org.freedesktop.DBus.Properties", "GetAll", "");
738}
739
zhanghch058d1b46d2021-04-01 11:18:24 +0800740inline void getDimmPartitionData(std::shared_ptr<bmcweb::AsyncResp> aResp,
Ed Tanous23a21a12020-07-25 04:45:05 +0000741 const std::string& service,
742 const std::string& path)
James Feist45094ad2020-04-29 14:02:30 -0700743{
744 crow::connections::systemBus->async_method_call(
745 [aResp{std::move(aResp)}](
746 const boost::system::error_code ec,
747 const boost::container::flat_map<
748 std::string, std::variant<std::string, uint64_t, uint32_t,
749 bool>>& properties) {
750 if (ec)
751 {
752 BMCWEB_LOG_DEBUG << "DBUS response error";
753 messages::internalError(aResp->res);
754
755 return;
756 }
757
758 nlohmann::json& partition =
759 aResp->res.jsonValue["Regions"].emplace_back(
760 nlohmann::json::object());
761 for (const auto& [key, val] : properties)
762 {
763 if (key == "MemoryClassification")
764 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700765 const std::string* value = std::get_if<std::string>(&val);
766 if (value == nullptr)
767 {
768 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +0800769 return;
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700770 }
771 partition[key] = *value;
James Feist45094ad2020-04-29 14:02:30 -0700772 }
773 else if (key == "OffsetInKiB")
774 {
775 const uint64_t* value = std::get_if<uint64_t>(&val);
776 if (value == nullptr)
777 {
778 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +0800779 return;
James Feist45094ad2020-04-29 14:02:30 -0700780 }
781
782 partition["OffsetMiB"] = (*value >> 10);
783 }
784 else if (key == "PartitionId")
785 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700786 const std::string* value = std::get_if<std::string>(&val);
787 if (value == nullptr)
788 {
789 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +0800790 return;
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700791 }
792 partition["RegionId"] = *value;
James Feist45094ad2020-04-29 14:02:30 -0700793 }
794
795 else if (key == "PassphraseState")
796 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700797 const bool* value = std::get_if<bool>(&val);
798 if (value == nullptr)
799 {
800 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +0800801 return;
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700802 }
803 partition["PassphraseEnabled"] = *value;
James Feist45094ad2020-04-29 14:02:30 -0700804 }
805 else if (key == "SizeInKiB")
806 {
807 const uint64_t* value = std::get_if<uint64_t>(&val);
808 if (value == nullptr)
809 {
810 messages::internalError(aResp->res);
811 BMCWEB_LOG_DEBUG
812 << "Invalid property type for SizeInKiB";
Chicago Duan601af5e2021-04-15 16:59:25 +0800813 return;
James Feist45094ad2020-04-29 14:02:30 -0700814 }
815 partition["SizeMiB"] = (*value >> 10);
816 }
817 }
818 },
819
820 service, path, "org.freedesktop.DBus.Properties", "GetAll",
821 "xyz.openbmc_project.Inventory.Item.PersistentMemory.Partition");
822}
823
zhanghch058d1b46d2021-04-01 11:18:24 +0800824inline void getDimmData(std::shared_ptr<bmcweb::AsyncResp> aResp,
Ed Tanous23a21a12020-07-25 04:45:05 +0000825 const std::string& dimmId)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200826{
827 BMCWEB_LOG_DEBUG << "Get available system dimm resources.";
828 crow::connections::systemBus->async_method_call(
Ed Tanous029573d2019-02-01 10:57:49 -0800829 [dimmId, aResp{std::move(aResp)}](
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200830 const boost::system::error_code ec,
831 const boost::container::flat_map<
832 std::string, boost::container::flat_map<
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500833 std::string, std::vector<std::string>>>&
834 subtree) {
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200835 if (ec)
836 {
837 BMCWEB_LOG_DEBUG << "DBUS response error";
838 messages::internalError(aResp->res);
839
840 return;
841 }
James Feist45094ad2020-04-29 14:02:30 -0700842 bool found = false;
843 for (const auto& [path, object] : subtree)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200844 {
James Feist45094ad2020-04-29 14:02:30 -0700845 if (path.find(dimmId) != std::string::npos)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200846 {
James Feist45094ad2020-04-29 14:02:30 -0700847 for (const auto& [service, interfaces] : object)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200848 {
James Feist45094ad2020-04-29 14:02:30 -0700849 if (!found &&
850 (std::find(
851 interfaces.begin(), interfaces.end(),
852 "xyz.openbmc_project.Inventory.Item.Dimm") !=
853 interfaces.end()))
854 {
855 getDimmDataByService(aResp, dimmId, service, path);
856 found = true;
857 }
858
859 // partitions are separate as there can be multiple per
860 // device, i.e.
861 // /xyz/openbmc_project/Inventory/Item/Dimm1/Partition1
862 // /xyz/openbmc_project/Inventory/Item/Dimm1/Partition2
George Liu0fda0f12021-11-16 10:06:17 +0800863 if (std::find(
864 interfaces.begin(), interfaces.end(),
865 "xyz.openbmc_project.Inventory.Item.PersistentMemory.Partition") !=
James Feist45094ad2020-04-29 14:02:30 -0700866 interfaces.end())
867 {
868 getDimmPartitionData(aResp, service, path);
869 }
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200870 }
871 }
872 }
873 // Object not found
James Feist45094ad2020-04-29 14:02:30 -0700874 if (!found)
875 {
876 messages::resourceNotFound(aResp->res, "Memory", dimmId);
877 }
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200878 return;
879 },
880 "xyz.openbmc_project.ObjectMapper",
881 "/xyz/openbmc_project/object_mapper",
882 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
Ed Tanous271584a2019-07-09 16:24:22 -0700883 "/xyz/openbmc_project/inventory", 0,
James Feist45094ad2020-04-29 14:02:30 -0700884 std::array<const char*, 2>{
885 "xyz.openbmc_project.Inventory.Item.Dimm",
886 "xyz.openbmc_project.Inventory.Item.PersistentMemory.Partition"});
Ed Tanous271584a2019-07-09 16:24:22 -0700887}
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200888
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700889inline void requestRoutesMemoryCollection(App& app)
Ed Tanous029573d2019-02-01 10:57:49 -0800890{
Ed Tanous029573d2019-02-01 10:57:49 -0800891 /**
892 * Functions triggers appropriate requests on DBus
893 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700894 BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/Memory/")
Ed Tanoused398212021-06-09 17:05:54 -0700895 .privileges(redfish::privileges::getMemoryCollection)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700896 .methods(boost::beast::http::verb::get)(
897 [](const crow::Request&,
898 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
899 asyncResp->res.jsonValue["@odata.type"] =
900 "#MemoryCollection.MemoryCollection";
901 asyncResp->res.jsonValue["Name"] = "Memory Module Collection";
902 asyncResp->res.jsonValue["@odata.id"] =
903 "/redfish/v1/Systems/system/Memory";
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200904
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700905 collection_util::getCollectionMembers(
906 asyncResp, "/redfish/v1/Systems/system/Memory",
907 {"xyz.openbmc_project.Inventory.Item.Dimm"});
908 });
909}
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200910
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700911inline void requestRoutesMemory(App& app)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200912{
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200913 /**
914 * Functions triggers appropriate requests on DBus
915 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700916 BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/Memory/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -0700917 .privileges(redfish::privileges::getMemory)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700918 .methods(boost::beast::http::verb::get)(
919 [](const crow::Request&,
920 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
921 const std::string& dimmId) {
922 asyncResp->res.jsonValue["@odata.type"] =
923 "#Memory.v1_11_0.Memory";
924 asyncResp->res.jsonValue["@odata.id"] =
925 "/redfish/v1/Systems/system/Memory/" + dimmId;
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200926
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700927 getDimmData(asyncResp, dimmId);
928 });
929}
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200930
931} // namespace redfish