blob: fb2dac147bd72d3a1479339a849dcae864aa1c9e [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>
Sui Chen7267c212022-05-17 14:49:28 -070021#include <boost/algorithm/string.hpp>
Ed Tanous168e20c2021-12-13 14:39:53 -080022#include <dbus_utility.hpp>
Ed Tanous45ca1b82022-03-25 13:07:27 -070023#include <query.hpp>
Ed Tanoused398212021-06-09 17:05:54 -070024#include <registries/privilege_registry.hpp>
Gunnar Mills116bcc52020-10-14 15:23:42 -050025#include <utils/collection.hpp>
Ed Tanousf201ffb2021-10-09 14:49:28 -070026#include <utils/hex_utils.hpp>
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +020027#include <utils/json_utils.hpp>
28
29namespace redfish
30{
31
Gunnar Mills313efb12020-10-26 16:05:08 -050032inline std::string translateMemoryTypeToRedfish(const std::string& memoryType)
33{
34 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR")
35 {
36 return "DDR";
37 }
38 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR2")
39 {
40 return "DDR2";
41 }
42 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR3")
43 {
44 return "DDR3";
45 }
46 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR4")
47 {
48 return "DDR4";
49 }
50 if (memoryType ==
51 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR4E_SDRAM")
52 {
53 return "DDR4E_SDRAM";
54 }
Mansi Joshi11a2f0f2021-07-19 14:33:27 +053055 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR5")
56 {
57 return "DDR5";
58 }
Gunnar Mills313efb12020-10-26 16:05:08 -050059 if (memoryType ==
60 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.LPDDR4_SDRAM")
61 {
62 return "LPDDR4_SDRAM";
63 }
64 if (memoryType ==
65 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.LPDDR3_SDRAM")
66 {
67 return "LPDDR3_SDRAM";
68 }
69 if (memoryType ==
70 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR2_SDRAM_FB_DIMM")
71 {
72 return "DDR2_SDRAM_FB_DIMM";
73 }
George Liu0fda0f12021-11-16 10:06:17 +080074 if (memoryType ==
75 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR2_SDRAM_FB_DIMM_PROB")
Gunnar Mills313efb12020-10-26 16:05:08 -050076 {
77 return "DDR2_SDRAM_FB_DIMM_PROBE";
78 }
79 if (memoryType ==
80 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR_SGRAM")
81 {
82 return "DDR_SGRAM";
83 }
84 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.ROM")
85 {
86 return "ROM";
87 }
88 if (memoryType ==
89 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.SDRAM")
90 {
91 return "SDRAM";
92 }
93 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.EDO")
94 {
95 return "EDO";
96 }
97 if (memoryType ==
98 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.FastPageMode")
99 {
100 return "FastPageMode";
101 }
102 if (memoryType ==
103 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.PipelinedNibble")
104 {
105 return "PipelinedNibble";
106 }
107 if (memoryType ==
108 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.Logical")
109 {
110 return "Logical";
111 }
112 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.HBM")
113 {
114 return "HBM";
115 }
116 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.HBM2")
117 {
118 return "HBM2";
119 }
120 // This is values like Other or Unknown
121 // Also D-Bus values:
122 // DRAM
123 // EDRAM
124 // VRAM
125 // SRAM
126 // RAM
127 // FLASH
128 // EEPROM
129 // FEPROM
130 // EPROM
131 // CDRAM
132 // ThreeDRAM
133 // RDRAM
134 // FBD2
135 // LPDDR_SDRAM
136 // LPDDR2_SDRAM
Mansi Joshi11a2f0f2021-07-19 14:33:27 +0530137 // LPDDR5_SDRAM
Gunnar Mills313efb12020-10-26 16:05:08 -0500138 return "";
139}
140
Ed Tanous168e20c2021-12-13 14:39:53 -0800141inline void dimmPropToHex(
142 const std::shared_ptr<bmcweb::AsyncResp>& aResp, const char* key,
143 const std::pair<std::string, dbus::utility::DbusVariantType>& property)
James Feistc50e7c62020-07-27 15:39:36 -0700144{
145 const uint16_t* value = std::get_if<uint16_t>(&property.second);
146 if (value == nullptr)
147 {
148 messages::internalError(aResp->res);
149 BMCWEB_LOG_DEBUG << "Invalid property type for " << property.first;
150 return;
151 }
152
Ed Tanous866e4862022-02-17 11:40:25 -0800153 aResp->res.jsonValue[key] = "0x" + intToHexString(*value, 4);
James Feistc50e7c62020-07-27 15:39:36 -0700154}
155
zhanghch058d1b46d2021-04-01 11:18:24 +0800156inline void getPersistentMemoryProperties(
157 const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800158 const std::pair<std::string, dbus::utility::DbusVariantType>& property)
James Feistc50e7c62020-07-27 15:39:36 -0700159{
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800160 if (property.first == "ModuleManufacturerID")
James Feistc50e7c62020-07-27 15:39:36 -0700161 {
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800162 dimmPropToHex(aResp, "ModuleManufacturerID", property);
163 }
164 else if (property.first == "ModuleProductID")
165 {
166 dimmPropToHex(aResp, "ModuleProductID", property);
167 }
168 else if (property.first == "SubsystemVendorID")
169 {
170 dimmPropToHex(aResp, "MemorySubsystemControllerManufacturerID",
171 property);
172 }
173 else if (property.first == "SubsystemDeviceID")
174 {
175 dimmPropToHex(aResp, "MemorySubsystemControllerProductID", property);
176 }
177 else if (property.first == "VolatileRegionSizeLimitInKiB")
178 {
179 const uint64_t* value = std::get_if<uint64_t>(&property.second);
James Feistc50e7c62020-07-27 15:39:36 -0700180
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800181 if (value == nullptr)
James Feistc50e7c62020-07-27 15:39:36 -0700182 {
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800183 messages::internalError(aResp->res);
184 BMCWEB_LOG_DEBUG
185 << "Invalid property type for VolatileRegionSizeLimitKiB";
186 return;
187 }
188 aResp->res.jsonValue["VolatileRegionSizeLimitMiB"] = (*value) >> 10;
189 }
190 else if (property.first == "PmRegionSizeLimitInKiB")
191 {
192 const uint64_t* value = std::get_if<uint64_t>(&property.second);
James Feistc50e7c62020-07-27 15:39:36 -0700193
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800194 if (value == nullptr)
James Feistc50e7c62020-07-27 15:39:36 -0700195 {
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800196 messages::internalError(aResp->res);
197 BMCWEB_LOG_DEBUG << "Invalid property type for PmRegioSizeLimitKiB";
198 return;
199 }
200 aResp->res.jsonValue["PersistentRegionSizeLimitMiB"] = (*value) >> 10;
201 }
202 else if (property.first == "VolatileSizeInKiB")
203 {
204 const uint64_t* value = std::get_if<uint64_t>(&property.second);
James Feistc50e7c62020-07-27 15:39:36 -0700205
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800206 if (value == nullptr)
James Feistc50e7c62020-07-27 15:39:36 -0700207 {
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800208 messages::internalError(aResp->res);
209 BMCWEB_LOG_DEBUG << "Invalid property type for VolatileSizeInKiB";
210 return;
James Feistc50e7c62020-07-27 15:39:36 -0700211 }
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800212 aResp->res.jsonValue["VolatileSizeMiB"] = (*value) >> 10;
213 }
214 else if (property.first == "PmSizeInKiB")
215 {
216 const uint64_t* value = std::get_if<uint64_t>(&property.second);
217 if (value == nullptr)
James Feistc50e7c62020-07-27 15:39:36 -0700218 {
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800219 messages::internalError(aResp->res);
220 BMCWEB_LOG_DEBUG << "Invalid property type for PmSizeInKiB";
221 return;
James Feistc50e7c62020-07-27 15:39:36 -0700222 }
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800223 aResp->res.jsonValue["NonVolatileSizeMiB"] = (*value) >> 10;
224 }
225 else if (property.first == "CacheSizeInKB")
226 {
227 const uint64_t* value = std::get_if<uint64_t>(&property.second);
228 if (value == nullptr)
229 {
230 messages::internalError(aResp->res);
231 BMCWEB_LOG_DEBUG << "Invalid property type for CacheSizeInKB";
232 return;
233 }
234 aResp->res.jsonValue["CacheSizeMiB"] = (*value >> 10);
235 }
James Feistc50e7c62020-07-27 15:39:36 -0700236
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800237 else if (property.first == "VoltaileRegionMaxSizeInKib")
238 {
239 const uint64_t* value = std::get_if<uint64_t>(&property.second);
James Feistc50e7c62020-07-27 15:39:36 -0700240
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800241 if (value == nullptr)
James Feistc50e7c62020-07-27 15:39:36 -0700242 {
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800243 messages::internalError(aResp->res);
244 BMCWEB_LOG_DEBUG
245 << "Invalid property type for VolatileRegionMaxSizeInKib";
246 return;
247 }
248 aResp->res.jsonValue["VolatileRegionSizeMaxMiB"] = (*value) >> 10;
249 }
250 else if (property.first == "PmRegionMaxSizeInKiB")
251 {
252 const uint64_t* value = std::get_if<uint64_t>(&property.second);
James Feistc50e7c62020-07-27 15:39:36 -0700253
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800254 if (value == nullptr)
James Feistc50e7c62020-07-27 15:39:36 -0700255 {
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800256 messages::internalError(aResp->res);
257 BMCWEB_LOG_DEBUG
258 << "Invalid property type for PmRegionMaxSizeInKiB";
259 return;
260 }
261 aResp->res.jsonValue["PersistentRegionSizeMaxMiB"] = (*value) >> 10;
262 }
263 else if (property.first == "AllocationIncrementInKiB")
264 {
265 const uint64_t* value = std::get_if<uint64_t>(&property.second);
James Feistc50e7c62020-07-27 15:39:36 -0700266
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800267 if (value == nullptr)
James Feistc50e7c62020-07-27 15:39:36 -0700268 {
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800269 messages::internalError(aResp->res);
270 BMCWEB_LOG_DEBUG
271 << "Invalid property type for AllocationIncrementInKiB";
272 return;
273 }
274 aResp->res.jsonValue["AllocationIncrementMiB"] = (*value) >> 10;
275 }
276 else if (property.first == "AllocationAlignmentInKiB")
277 {
278 const uint64_t* value = std::get_if<uint64_t>(&property.second);
James Feistc50e7c62020-07-27 15:39:36 -0700279
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800280 if (value == nullptr)
James Feistc50e7c62020-07-27 15:39:36 -0700281 {
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800282 messages::internalError(aResp->res);
283 BMCWEB_LOG_DEBUG
284 << "Invalid property type for AllocationAlignmentInKiB";
285 return;
James Feistc50e7c62020-07-27 15:39:36 -0700286 }
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800287 aResp->res.jsonValue["AllocationAlignmentMiB"] = (*value) >> 10;
288 }
289 else if (property.first == "VolatileRegionNumberLimit")
290 {
291 const uint64_t* value = std::get_if<uint64_t>(&property.second);
292 if (value == nullptr)
James Feistc50e7c62020-07-27 15:39:36 -0700293 {
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800294 messages::internalError(aResp->res);
295 return;
James Feistc50e7c62020-07-27 15:39:36 -0700296 }
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800297 aResp->res.jsonValue["VolatileRegionNumberLimit"] = *value;
298 }
299 else if (property.first == "PmRegionNumberLimit")
300 {
301 const uint64_t* value = std::get_if<uint64_t>(&property.second);
302 if (value == nullptr)
James Feistc50e7c62020-07-27 15:39:36 -0700303 {
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800304 messages::internalError(aResp->res);
305 return;
James Feistc50e7c62020-07-27 15:39:36 -0700306 }
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800307 aResp->res.jsonValue["PersistentRegionNumberLimit"] = *value;
308 }
309 else if (property.first == "SpareDeviceCount")
310 {
311 const uint64_t* value = std::get_if<uint64_t>(&property.second);
312 if (value == nullptr)
James Feistc50e7c62020-07-27 15:39:36 -0700313 {
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800314 messages::internalError(aResp->res);
315 return;
James Feistc50e7c62020-07-27 15:39:36 -0700316 }
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800317 aResp->res.jsonValue["SpareDeviceCount"] = *value;
318 }
319 else if (property.first == "IsSpareDeviceInUse")
320 {
321 const bool* value = std::get_if<bool>(&property.second);
322 if (value == nullptr)
James Feistc50e7c62020-07-27 15:39:36 -0700323 {
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800324 messages::internalError(aResp->res);
325 return;
James Feistc50e7c62020-07-27 15:39:36 -0700326 }
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800327 aResp->res.jsonValue["IsSpareDeviceEnabled"] = *value;
328 }
329 else if (property.first == "IsRankSpareEnabled")
330 {
331 const bool* value = std::get_if<bool>(&property.second);
332 if (value == nullptr)
James Feistc50e7c62020-07-27 15:39:36 -0700333 {
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800334 messages::internalError(aResp->res);
335 return;
James Feistc50e7c62020-07-27 15:39:36 -0700336 }
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800337 aResp->res.jsonValue["IsRankSpareEnabled"] = *value;
338 }
339 else if (property.first == "MaxAveragePowerLimitmW")
340 {
341 const auto* value =
342 std::get_if<std::vector<uint32_t>>(&property.second);
343 if (value == nullptr)
James Feistc50e7c62020-07-27 15:39:36 -0700344 {
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800345 messages::internalError(aResp->res);
346 BMCWEB_LOG_DEBUG
347 << "Invalid property type for MaxAveragePowerLimitmW";
348 return;
James Feistc50e7c62020-07-27 15:39:36 -0700349 }
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800350 aResp->res.jsonValue["MaxTDPMilliWatts"] = *value;
351 }
352 else if (property.first == "ConfigurationLocked")
353 {
354 const bool* value = std::get_if<bool>(&property.second);
355 if (value == nullptr)
James Feistc50e7c62020-07-27 15:39:36 -0700356 {
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800357 messages::internalError(aResp->res);
358 return;
359 }
360 aResp->res.jsonValue["ConfigurationLocked"] = *value;
361 }
362 else if (property.first == "AllowedMemoryModes")
363 {
364 const std::string* value = std::get_if<std::string>(&property.second);
365 if (value == nullptr)
366 {
367 messages::internalError(aResp->res);
368 BMCWEB_LOG_DEBUG << "Invalid property type for FormFactor";
369 return;
370 }
371 constexpr const std::array<const char*, 3> values{"Volatile", "PMEM",
372 "Block"};
James Feistc50e7c62020-07-27 15:39:36 -0700373
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800374 for (const char* v : values)
375 {
376 if (boost::ends_with(*value, v))
James Feistc50e7c62020-07-27 15:39:36 -0700377 {
Jiaqing Zhao1e04f3b2022-03-18 17:24:32 +0800378 aResp->res.jsonValue["OperatingMemoryModes"].push_back(v);
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800379 break;
James Feistc50e7c62020-07-27 15:39:36 -0700380 }
381 }
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800382 }
383 else if (property.first == "MemoryMedia")
384 {
385 const std::string* value = std::get_if<std::string>(&property.second);
386 if (value == nullptr)
James Feistc50e7c62020-07-27 15:39:36 -0700387 {
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800388 messages::internalError(aResp->res);
389 BMCWEB_LOG_DEBUG << "Invalid property type for MemoryMedia";
390 return;
391 }
392 constexpr const std::array<const char*, 3> values{"DRAM", "NAND",
393 "Intel3DXPoint"};
James Feistc50e7c62020-07-27 15:39:36 -0700394
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800395 for (const char* v : values)
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700396 {
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800397 if (boost::ends_with(*value, v))
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700398 {
Jiaqing Zhao1e04f3b2022-03-18 17:24:32 +0800399 aResp->res.jsonValue["MemoryMedia"].push_back(v);
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800400 break;
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700401 }
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700402 }
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800403 }
404 // PersistantMemory.SecurityCapabilites interface
405 else if (property.first == "ConfigurationLockCapable" ||
406 property.first == "DataLockCapable" ||
407 property.first == "PassphraseCapable")
408 {
409 const bool* value = std::get_if<bool>(&property.second);
410 if (value == nullptr)
James Feistc50e7c62020-07-27 15:39:36 -0700411 {
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800412 messages::internalError(aResp->res);
413 return;
James Feistc50e7c62020-07-27 15:39:36 -0700414 }
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800415 aResp->res.jsonValue["SecurityCapabilities"][property.first] = *value;
416 }
417 else if (property.first == "MaxPassphraseCount" ||
418 property.first == "PassphraseLockLimit")
419 {
420 const uint64_t* value = std::get_if<uint64_t>(&property.second);
421 if (value == nullptr)
422 {
423 messages::internalError(aResp->res);
424 return;
425 }
426 aResp->res.jsonValue["SecurityCapabilities"][property.first] = *value;
James Feistc50e7c62020-07-27 15:39:36 -0700427 }
428}
429
Nan Zhou9a5acea2022-05-17 21:12:43 +0000430inline void
431 assembleDimmProperties(std::string_view dimmId,
432 const std::shared_ptr<bmcweb::AsyncResp>& aResp,
433 const dbus::utility::DBusPropertiesMap& properties)
434{
435 aResp->res.jsonValue["Id"] = dimmId;
436 aResp->res.jsonValue["Name"] = "DIMM Slot";
437 aResp->res.jsonValue["Status"]["State"] = "Enabled";
438 aResp->res.jsonValue["Status"]["Health"] = "OK";
439
440 for (const auto& property : properties)
441 {
442 if (property.first == "MemoryDataWidth")
443 {
444 const uint16_t* value = std::get_if<uint16_t>(&property.second);
445 if (value == nullptr)
446 {
447 continue;
448 }
449 aResp->res.jsonValue["DataWidthBits"] = *value;
450 }
451 else if (property.first == "MemorySizeInKB")
452 {
453 const size_t* memorySize = std::get_if<size_t>(&property.second);
454 if (memorySize == nullptr)
455 {
456 // Important property not in desired type
457 messages::internalError(aResp->res);
458 return;
459 }
460 aResp->res.jsonValue["CapacityMiB"] = (*memorySize >> 10);
461 }
462 else if (property.first == "PartNumber")
463 {
464 const std::string* value =
465 std::get_if<std::string>(&property.second);
466 if (value == nullptr)
467 {
468 continue;
469 }
470 aResp->res.jsonValue["PartNumber"] = *value;
471 }
472 else if (property.first == "SerialNumber")
473 {
474 const std::string* value =
475 std::get_if<std::string>(&property.second);
476 if (value == nullptr)
477 {
478 continue;
479 }
480 aResp->res.jsonValue["SerialNumber"] = *value;
481 }
482 else if (property.first == "Manufacturer")
483 {
484 const std::string* value =
485 std::get_if<std::string>(&property.second);
486 if (value == nullptr)
487 {
488 continue;
489 }
490 aResp->res.jsonValue["Manufacturer"] = *value;
491 }
492 else if (property.first == "RevisionCode")
493 {
494 const uint16_t* value = std::get_if<uint16_t>(&property.second);
495
496 if (value == nullptr)
497 {
498 messages::internalError(aResp->res);
499 BMCWEB_LOG_DEBUG << "Invalid property type for RevisionCode";
500 return;
501 }
502 aResp->res.jsonValue["FirmwareRevision"] = std::to_string(*value);
503 }
504 else if (property.first == "Present")
505 {
506 const bool* value = std::get_if<bool>(&property.second);
507 if (value == nullptr)
508 {
509 messages::internalError(aResp->res);
510 BMCWEB_LOG_DEBUG << "Invalid property type for Dimm Presence";
511 return;
512 }
513 if (!*value)
514 {
515 aResp->res.jsonValue["Status"]["State"] = "Absent";
516 }
517 }
518 else if (property.first == "MemoryTotalWidth")
519 {
520 const uint16_t* value = std::get_if<uint16_t>(&property.second);
521 if (value == nullptr)
522 {
523 continue;
524 }
525 aResp->res.jsonValue["BusWidthBits"] = *value;
526 }
527 else if (property.first == "ECC")
528 {
529 const std::string* value =
530 std::get_if<std::string>(&property.second);
531 if (value == nullptr)
532 {
533 messages::internalError(aResp->res);
534 BMCWEB_LOG_DEBUG << "Invalid property type for ECC";
535 return;
536 }
537 constexpr const std::array<const char*, 4> values{
538 "NoECC", "SingleBitECC", "MultiBitECC", "AddressParity"};
539
540 for (const char* v : values)
541 {
542 if (boost::ends_with(*value, v))
543 {
544 aResp->res.jsonValue["ErrorCorrection"] = v;
545 break;
546 }
547 }
548 }
549 else if (property.first == "FormFactor")
550 {
551 const std::string* value =
552 std::get_if<std::string>(&property.second);
553 if (value == nullptr)
554 {
555 messages::internalError(aResp->res);
556 BMCWEB_LOG_DEBUG << "Invalid property type for FormFactor";
557 return;
558 }
559 constexpr const std::array<const char*, 11> values{
560 "RDIMM", "UDIMM", "SO_DIMM", "LRDIMM",
561 "Mini_RDIMM", "Mini_UDIMM", "SO_RDIMM_72b", "SO_UDIMM_72b",
562 "SO_DIMM_16b", "SO_DIMM_32b", "Die"};
563
564 for (const char* v : values)
565 {
566 if (boost::ends_with(*value, v))
567 {
568 aResp->res.jsonValue["BaseModuleType"] = v;
569 break;
570 }
571 }
572 }
573 else if (property.first == "AllowedSpeedsMT")
574 {
575 const std::vector<uint16_t>* value =
576 std::get_if<std::vector<uint16_t>>(&property.second);
577 if (value == nullptr)
578 {
579 continue;
580 }
581 nlohmann::json& jValue = aResp->res.jsonValue["AllowedSpeedsMHz"];
582 jValue = nlohmann::json::array();
583 for (uint16_t subVal : *value)
584 {
585 jValue.push_back(subVal);
586 }
587 }
588 else if (property.first == "MemoryAttributes")
589 {
590 const uint8_t* value = std::get_if<uint8_t>(&property.second);
591
592 if (value == nullptr)
593 {
594 messages::internalError(aResp->res);
595 BMCWEB_LOG_DEBUG
596 << "Invalid property type for MemoryAttributes";
597 return;
598 }
599 aResp->res.jsonValue["RankCount"] = static_cast<uint64_t>(*value);
600 }
601 else if (property.first == "MemoryConfiguredSpeedInMhz")
602 {
603 const uint16_t* value = std::get_if<uint16_t>(&property.second);
604 if (value == nullptr)
605 {
606 continue;
607 }
608 aResp->res.jsonValue["OperatingSpeedMhz"] = *value;
609 }
610 else if (property.first == "MemoryType")
611 {
612 const auto* value = std::get_if<std::string>(&property.second);
613 if (value != nullptr)
614 {
615 std::string memoryDeviceType =
616 translateMemoryTypeToRedfish(*value);
617 // Values like "Unknown" or "Other" will return empty
618 // so just leave off
619 if (!memoryDeviceType.empty())
620 {
621 aResp->res.jsonValue["MemoryDeviceType"] = memoryDeviceType;
622 }
623 if (value->find("DDR") != std::string::npos)
624 {
625 aResp->res.jsonValue["MemoryType"] = "DRAM";
626 }
627 else if (boost::ends_with(*value, "Logical"))
628 {
629 aResp->res.jsonValue["MemoryType"] = "IntelOptane";
630 }
631 }
632 }
633 // memory location interface
634 else if (property.first == "Channel" ||
635 property.first == "MemoryController" ||
636 property.first == "Slot" || property.first == "Socket")
637 {
638 const std::string* value =
639 std::get_if<std::string>(&property.second);
640 if (value == nullptr)
641 {
642 messages::internalError(aResp->res);
643 return;
644 }
645 aResp->res.jsonValue["MemoryLocation"][property.first] = *value;
646 }
647 else if (property.first == "SparePartNumber")
648 {
649 const std::string* value =
650 std::get_if<std::string>(&property.second);
651 if (value == nullptr)
652 {
653 messages::internalError(aResp->res);
654 return;
655 }
656 aResp->res.jsonValue["SparePartNumber"] = *value;
657 }
658 else if (property.first == "Model")
659 {
660 const std::string* value =
661 std::get_if<std::string>(&property.second);
662 if (value == nullptr)
663 {
664 messages::internalError(aResp->res);
665 return;
666 }
667 aResp->res.jsonValue["Model"] = *value;
668 }
669 else if (property.first == "LocationCode")
670 {
671 const std::string* value =
672 std::get_if<std::string>(&property.second);
673 if (value == nullptr)
674 {
675 messages::internalError(aResp->res);
676 return;
677 }
678 aResp->res.jsonValue["Location"]["PartLocation"]["ServiceLabel"] =
679 *value;
680 }
681 else
682 {
683 getPersistentMemoryProperties(aResp, property);
684 }
685 }
686}
687
zhanghch058d1b46d2021-04-01 11:18:24 +0800688inline void getDimmDataByService(std::shared_ptr<bmcweb::AsyncResp> aResp,
Ed Tanous80789c82020-08-19 09:19:09 -0700689 const std::string& dimmId,
690 const std::string& service,
691 const std::string& objPath)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200692{
James Feist35e257a2020-06-05 13:30:51 -0700693 auto health = std::make_shared<HealthPopulate>(aResp);
694 health->selfPath = objPath;
695 health->populate();
696
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200697 BMCWEB_LOG_DEBUG << "Get available system components.";
698 crow::connections::systemBus->async_method_call(
Ed Tanousb9d36b42022-02-26 21:42:46 -0800699 [dimmId, aResp{std::move(aResp)}](
700 const boost::system::error_code ec,
701 const dbus::utility::DBusPropertiesMap& properties) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700702 if (ec)
703 {
704 BMCWEB_LOG_DEBUG << "DBUS response error";
705 messages::internalError(aResp->res);
706 return;
707 }
708 assembleDimmProperties(dimmId, aResp, properties);
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200709 },
710 service, objPath, "org.freedesktop.DBus.Properties", "GetAll", "");
711}
712
Nan Zhouef00d7d2022-05-20 21:22:32 +0000713inline void assembleDimmPartitionData(
714 const std::shared_ptr<bmcweb::AsyncResp>& aResp,
715 const dbus::utility::DBusPropertiesMap& properties)
716{
717 nlohmann::json& partition =
718 aResp->res.jsonValue["Regions"].emplace_back(nlohmann::json::object());
719 for (const auto& [key, val] : properties)
720 {
721 if (key == "MemoryClassification")
722 {
723 const std::string* value = std::get_if<std::string>(&val);
724 if (value == nullptr)
725 {
726 messages::internalError(aResp->res);
727 return;
728 }
729 partition[key] = *value;
730 }
731 else if (key == "OffsetInKiB")
732 {
733 const uint64_t* value = std::get_if<uint64_t>(&val);
734 if (value == nullptr)
735 {
736 messages::internalError(aResp->res);
737 return;
738 }
739
740 partition["OffsetMiB"] = (*value >> 10);
741 }
742 else if (key == "PartitionId")
743 {
744 const std::string* value = std::get_if<std::string>(&val);
745 if (value == nullptr)
746 {
747 messages::internalError(aResp->res);
748 return;
749 }
750 partition["RegionId"] = *value;
751 }
752
753 else if (key == "PassphraseState")
754 {
755 const bool* value = std::get_if<bool>(&val);
756 if (value == nullptr)
757 {
758 messages::internalError(aResp->res);
759 return;
760 }
761 partition["PassphraseEnabled"] = *value;
762 }
763 else if (key == "SizeInKiB")
764 {
765 const uint64_t* value = std::get_if<uint64_t>(&val);
766 if (value == nullptr)
767 {
768 messages::internalError(aResp->res);
769 BMCWEB_LOG_DEBUG << "Invalid property type for SizeInKiB";
770 return;
771 }
772 partition["SizeMiB"] = (*value >> 10);
773 }
774 }
775}
776
zhanghch058d1b46d2021-04-01 11:18:24 +0800777inline void getDimmPartitionData(std::shared_ptr<bmcweb::AsyncResp> aResp,
Ed Tanous23a21a12020-07-25 04:45:05 +0000778 const std::string& service,
779 const std::string& path)
James Feist45094ad2020-04-29 14:02:30 -0700780{
781 crow::connections::systemBus->async_method_call(
782 [aResp{std::move(aResp)}](
783 const boost::system::error_code ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -0800784 const dbus::utility::DBusPropertiesMap& properties) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700785 if (ec)
786 {
787 BMCWEB_LOG_DEBUG << "DBUS response error";
788 messages::internalError(aResp->res);
James Feist45094ad2020-04-29 14:02:30 -0700789
Ed Tanous002d39b2022-05-31 08:59:27 -0700790 return;
791 }
792 assembleDimmPartitionData(aResp, properties);
James Feist45094ad2020-04-29 14:02:30 -0700793 },
794
795 service, path, "org.freedesktop.DBus.Properties", "GetAll",
796 "xyz.openbmc_project.Inventory.Item.PersistentMemory.Partition");
797}
798
Sui Chen7267c212022-05-17 14:49:28 -0700799inline bool pathContainsDimmId(const std::string& path, std::string_view dimmId)
800{
801 sdbusplus::message::object_path objectPath(path);
802 // for /xyz/openbmc_project/Inventory/Item/Dimm1/Partition1 or
803 // /xyz/openbmc_project/Inventory/Item/Dimm1
804 return !dimmId.empty() && (objectPath.filename() == dimmId ||
805 objectPath.parent_path().filename() == dimmId);
806}
807
zhanghch058d1b46d2021-04-01 11:18:24 +0800808inline void getDimmData(std::shared_ptr<bmcweb::AsyncResp> aResp,
Ed Tanous23a21a12020-07-25 04:45:05 +0000809 const std::string& dimmId)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200810{
811 BMCWEB_LOG_DEBUG << "Get available system dimm resources.";
812 crow::connections::systemBus->async_method_call(
Ed Tanous029573d2019-02-01 10:57:49 -0800813 [dimmId, aResp{std::move(aResp)}](
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200814 const boost::system::error_code ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -0800815 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700816 if (ec)
817 {
818 BMCWEB_LOG_DEBUG << "DBUS response error";
819 messages::internalError(aResp->res);
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200820
Ed Tanous002d39b2022-05-31 08:59:27 -0700821 return;
822 }
823 bool found = false;
824 for (const auto& [path, object] : subtree)
825 {
Sui Chen7267c212022-05-17 14:49:28 -0700826 if (pathContainsDimmId(path, dimmId))
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200827 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700828 for (const auto& [service, interfaces] : object)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200829 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700830 for (const auto& interface : interfaces)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200831 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700832 if (interface ==
833 "xyz.openbmc_project.Inventory.Item.Dimm")
James Feist45094ad2020-04-29 14:02:30 -0700834 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700835 getDimmDataByService(aResp, dimmId, service, path);
836 found = true;
837 }
James Feist45094ad2020-04-29 14:02:30 -0700838
Ed Tanous002d39b2022-05-31 08:59:27 -0700839 // partitions are separate as there can be multiple
840 // per
841 // device, i.e.
842 // /xyz/openbmc_project/Inventory/Item/Dimm1/Partition1
843 // /xyz/openbmc_project/Inventory/Item/Dimm1/Partition2
844 if (interface ==
845 "xyz.openbmc_project.Inventory.Item.PersistentMemory.Partition")
846 {
847 getDimmPartitionData(aResp, service, path);
James Feist45094ad2020-04-29 14:02:30 -0700848 }
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200849 }
850 }
851 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700852 }
853 // Object not found
854 if (!found)
855 {
856 messages::resourceNotFound(aResp->res, "Memory", dimmId);
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200857 return;
Ed Tanous002d39b2022-05-31 08:59:27 -0700858 }
859 // Set @odata only if object is found
860 aResp->res.jsonValue["@odata.type"] = "#Memory.v1_11_0.Memory";
861 aResp->res.jsonValue["@odata.id"] =
862 "/redfish/v1/Systems/system/Memory/" + dimmId;
863 return;
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200864 },
865 "xyz.openbmc_project.ObjectMapper",
866 "/xyz/openbmc_project/object_mapper",
867 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
Ed Tanous271584a2019-07-09 16:24:22 -0700868 "/xyz/openbmc_project/inventory", 0,
James Feist45094ad2020-04-29 14:02:30 -0700869 std::array<const char*, 2>{
870 "xyz.openbmc_project.Inventory.Item.Dimm",
871 "xyz.openbmc_project.Inventory.Item.PersistentMemory.Partition"});
Ed Tanous271584a2019-07-09 16:24:22 -0700872}
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200873
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700874inline void requestRoutesMemoryCollection(App& app)
Ed Tanous029573d2019-02-01 10:57:49 -0800875{
Ed Tanous029573d2019-02-01 10:57:49 -0800876 /**
877 * Functions triggers appropriate requests on DBus
878 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700879 BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/Memory/")
Ed Tanoused398212021-06-09 17:05:54 -0700880 .privileges(redfish::privileges::getMemoryCollection)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700881 .methods(boost::beast::http::verb::get)(
Ed Tanous45ca1b82022-03-25 13:07:27 -0700882 [&app](const crow::Request& req,
883 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
Carson Labrado3ba00072022-06-06 19:40:56 +0000884 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -0700885 {
886 return;
887 }
888 asyncResp->res.jsonValue["@odata.type"] =
889 "#MemoryCollection.MemoryCollection";
890 asyncResp->res.jsonValue["Name"] = "Memory Module Collection";
891 asyncResp->res.jsonValue["@odata.id"] =
892 "/redfish/v1/Systems/system/Memory";
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200893
Ed Tanous002d39b2022-05-31 08:59:27 -0700894 collection_util::getCollectionMembers(
895 asyncResp, "/redfish/v1/Systems/system/Memory",
896 {"xyz.openbmc_project.Inventory.Item.Dimm"});
897 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700898}
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200899
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700900inline void requestRoutesMemory(App& app)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200901{
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200902 /**
903 * Functions triggers appropriate requests on DBus
904 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700905 BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/Memory/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -0700906 .privileges(redfish::privileges::getMemory)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700907 .methods(boost::beast::http::verb::get)(
Ed Tanous45ca1b82022-03-25 13:07:27 -0700908 [&app](const crow::Request& req,
909 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
910 const std::string& dimmId) {
Carson Labrado3ba00072022-06-06 19:40:56 +0000911 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -0700912 {
913 return;
914 }
915 getDimmData(asyncResp, dimmId);
916 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700917}
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200918
919} // namespace redfish