blob: 6d035142da8d00c849e08cbd10f19a87c326fe17 [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>
Ed Tanous168e20c2021-12-13 14:39:53 -080021#include <dbus_utility.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
Gunnar Mills313efb12020-10-26 16:05:08 -050030inline std::string translateMemoryTypeToRedfish(const std::string& memoryType)
31{
32 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR")
33 {
34 return "DDR";
35 }
36 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR2")
37 {
38 return "DDR2";
39 }
40 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR3")
41 {
42 return "DDR3";
43 }
44 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR4")
45 {
46 return "DDR4";
47 }
48 if (memoryType ==
49 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR4E_SDRAM")
50 {
51 return "DDR4E_SDRAM";
52 }
Mansi Joshi11a2f0f2021-07-19 14:33:27 +053053 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR5")
54 {
55 return "DDR5";
56 }
Gunnar Mills313efb12020-10-26 16:05:08 -050057 if (memoryType ==
58 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.LPDDR4_SDRAM")
59 {
60 return "LPDDR4_SDRAM";
61 }
62 if (memoryType ==
63 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.LPDDR3_SDRAM")
64 {
65 return "LPDDR3_SDRAM";
66 }
67 if (memoryType ==
68 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR2_SDRAM_FB_DIMM")
69 {
70 return "DDR2_SDRAM_FB_DIMM";
71 }
George Liu0fda0f12021-11-16 10:06:17 +080072 if (memoryType ==
73 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR2_SDRAM_FB_DIMM_PROB")
Gunnar Mills313efb12020-10-26 16:05:08 -050074 {
75 return "DDR2_SDRAM_FB_DIMM_PROBE";
76 }
77 if (memoryType ==
78 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR_SGRAM")
79 {
80 return "DDR_SGRAM";
81 }
82 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.ROM")
83 {
84 return "ROM";
85 }
86 if (memoryType ==
87 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.SDRAM")
88 {
89 return "SDRAM";
90 }
91 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.EDO")
92 {
93 return "EDO";
94 }
95 if (memoryType ==
96 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.FastPageMode")
97 {
98 return "FastPageMode";
99 }
100 if (memoryType ==
101 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.PipelinedNibble")
102 {
103 return "PipelinedNibble";
104 }
105 if (memoryType ==
106 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.Logical")
107 {
108 return "Logical";
109 }
110 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.HBM")
111 {
112 return "HBM";
113 }
114 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.HBM2")
115 {
116 return "HBM2";
117 }
118 // This is values like Other or Unknown
119 // Also D-Bus values:
120 // DRAM
121 // EDRAM
122 // VRAM
123 // SRAM
124 // RAM
125 // FLASH
126 // EEPROM
127 // FEPROM
128 // EPROM
129 // CDRAM
130 // ThreeDRAM
131 // RDRAM
132 // FBD2
133 // LPDDR_SDRAM
134 // LPDDR2_SDRAM
Mansi Joshi11a2f0f2021-07-19 14:33:27 +0530135 // LPDDR5_SDRAM
Gunnar Mills313efb12020-10-26 16:05:08 -0500136 return "";
137}
138
Ed Tanous168e20c2021-12-13 14:39:53 -0800139inline void dimmPropToHex(
140 const std::shared_ptr<bmcweb::AsyncResp>& aResp, const char* key,
141 const std::pair<std::string, dbus::utility::DbusVariantType>& property)
James Feistc50e7c62020-07-27 15:39:36 -0700142{
143 const uint16_t* value = std::get_if<uint16_t>(&property.second);
144 if (value == nullptr)
145 {
146 messages::internalError(aResp->res);
147 BMCWEB_LOG_DEBUG << "Invalid property type for " << property.first;
148 return;
149 }
150
Ed Tanous866e4862022-02-17 11:40:25 -0800151 aResp->res.jsonValue[key] = "0x" + intToHexString(*value, 4);
James Feistc50e7c62020-07-27 15:39:36 -0700152}
153
zhanghch058d1b46d2021-04-01 11:18:24 +0800154inline void getPersistentMemoryProperties(
155 const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800156 const std::pair<std::string, dbus::utility::DbusVariantType>& property)
James Feistc50e7c62020-07-27 15:39:36 -0700157{
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800158 if (property.first == "ModuleManufacturerID")
James Feistc50e7c62020-07-27 15:39:36 -0700159 {
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800160 dimmPropToHex(aResp, "ModuleManufacturerID", property);
161 }
162 else if (property.first == "ModuleProductID")
163 {
164 dimmPropToHex(aResp, "ModuleProductID", property);
165 }
166 else if (property.first == "SubsystemVendorID")
167 {
168 dimmPropToHex(aResp, "MemorySubsystemControllerManufacturerID",
169 property);
170 }
171 else if (property.first == "SubsystemDeviceID")
172 {
173 dimmPropToHex(aResp, "MemorySubsystemControllerProductID", property);
174 }
175 else if (property.first == "VolatileRegionSizeLimitInKiB")
176 {
177 const uint64_t* value = std::get_if<uint64_t>(&property.second);
James Feistc50e7c62020-07-27 15:39:36 -0700178
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800179 if (value == nullptr)
James Feistc50e7c62020-07-27 15:39:36 -0700180 {
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800181 messages::internalError(aResp->res);
182 BMCWEB_LOG_DEBUG
183 << "Invalid property type for VolatileRegionSizeLimitKiB";
184 return;
185 }
186 aResp->res.jsonValue["VolatileRegionSizeLimitMiB"] = (*value) >> 10;
187 }
188 else if (property.first == "PmRegionSizeLimitInKiB")
189 {
190 const uint64_t* value = std::get_if<uint64_t>(&property.second);
James Feistc50e7c62020-07-27 15:39:36 -0700191
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800192 if (value == nullptr)
James Feistc50e7c62020-07-27 15:39:36 -0700193 {
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800194 messages::internalError(aResp->res);
195 BMCWEB_LOG_DEBUG << "Invalid property type for PmRegioSizeLimitKiB";
196 return;
197 }
198 aResp->res.jsonValue["PersistentRegionSizeLimitMiB"] = (*value) >> 10;
199 }
200 else if (property.first == "VolatileSizeInKiB")
201 {
202 const uint64_t* value = std::get_if<uint64_t>(&property.second);
James Feistc50e7c62020-07-27 15:39:36 -0700203
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800204 if (value == nullptr)
James Feistc50e7c62020-07-27 15:39:36 -0700205 {
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800206 messages::internalError(aResp->res);
207 BMCWEB_LOG_DEBUG << "Invalid property type for VolatileSizeInKiB";
208 return;
James Feistc50e7c62020-07-27 15:39:36 -0700209 }
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800210 aResp->res.jsonValue["VolatileSizeMiB"] = (*value) >> 10;
211 }
212 else if (property.first == "PmSizeInKiB")
213 {
214 const uint64_t* value = std::get_if<uint64_t>(&property.second);
215 if (value == nullptr)
James Feistc50e7c62020-07-27 15:39:36 -0700216 {
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800217 messages::internalError(aResp->res);
218 BMCWEB_LOG_DEBUG << "Invalid property type for PmSizeInKiB";
219 return;
James Feistc50e7c62020-07-27 15:39:36 -0700220 }
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800221 aResp->res.jsonValue["NonVolatileSizeMiB"] = (*value) >> 10;
222 }
223 else if (property.first == "CacheSizeInKB")
224 {
225 const uint64_t* value = std::get_if<uint64_t>(&property.second);
226 if (value == nullptr)
227 {
228 messages::internalError(aResp->res);
229 BMCWEB_LOG_DEBUG << "Invalid property type for CacheSizeInKB";
230 return;
231 }
232 aResp->res.jsonValue["CacheSizeMiB"] = (*value >> 10);
233 }
James Feistc50e7c62020-07-27 15:39:36 -0700234
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800235 else if (property.first == "VoltaileRegionMaxSizeInKib")
236 {
237 const uint64_t* value = std::get_if<uint64_t>(&property.second);
James Feistc50e7c62020-07-27 15:39:36 -0700238
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800239 if (value == nullptr)
James Feistc50e7c62020-07-27 15:39:36 -0700240 {
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800241 messages::internalError(aResp->res);
242 BMCWEB_LOG_DEBUG
243 << "Invalid property type for VolatileRegionMaxSizeInKib";
244 return;
245 }
246 aResp->res.jsonValue["VolatileRegionSizeMaxMiB"] = (*value) >> 10;
247 }
248 else if (property.first == "PmRegionMaxSizeInKiB")
249 {
250 const uint64_t* value = std::get_if<uint64_t>(&property.second);
James Feistc50e7c62020-07-27 15:39:36 -0700251
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800252 if (value == nullptr)
James Feistc50e7c62020-07-27 15:39:36 -0700253 {
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800254 messages::internalError(aResp->res);
255 BMCWEB_LOG_DEBUG
256 << "Invalid property type for PmRegionMaxSizeInKiB";
257 return;
258 }
259 aResp->res.jsonValue["PersistentRegionSizeMaxMiB"] = (*value) >> 10;
260 }
261 else if (property.first == "AllocationIncrementInKiB")
262 {
263 const uint64_t* value = std::get_if<uint64_t>(&property.second);
James Feistc50e7c62020-07-27 15:39:36 -0700264
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800265 if (value == nullptr)
James Feistc50e7c62020-07-27 15:39:36 -0700266 {
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800267 messages::internalError(aResp->res);
268 BMCWEB_LOG_DEBUG
269 << "Invalid property type for AllocationIncrementInKiB";
270 return;
271 }
272 aResp->res.jsonValue["AllocationIncrementMiB"] = (*value) >> 10;
273 }
274 else if (property.first == "AllocationAlignmentInKiB")
275 {
276 const uint64_t* value = std::get_if<uint64_t>(&property.second);
James Feistc50e7c62020-07-27 15:39:36 -0700277
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800278 if (value == nullptr)
James Feistc50e7c62020-07-27 15:39:36 -0700279 {
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800280 messages::internalError(aResp->res);
281 BMCWEB_LOG_DEBUG
282 << "Invalid property type for AllocationAlignmentInKiB";
283 return;
James Feistc50e7c62020-07-27 15:39:36 -0700284 }
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800285 aResp->res.jsonValue["AllocationAlignmentMiB"] = (*value) >> 10;
286 }
287 else if (property.first == "VolatileRegionNumberLimit")
288 {
289 const uint64_t* value = std::get_if<uint64_t>(&property.second);
290 if (value == nullptr)
James Feistc50e7c62020-07-27 15:39:36 -0700291 {
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800292 messages::internalError(aResp->res);
293 return;
James Feistc50e7c62020-07-27 15:39:36 -0700294 }
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800295 aResp->res.jsonValue["VolatileRegionNumberLimit"] = *value;
296 }
297 else if (property.first == "PmRegionNumberLimit")
298 {
299 const uint64_t* value = std::get_if<uint64_t>(&property.second);
300 if (value == nullptr)
James Feistc50e7c62020-07-27 15:39:36 -0700301 {
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800302 messages::internalError(aResp->res);
303 return;
James Feistc50e7c62020-07-27 15:39:36 -0700304 }
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800305 aResp->res.jsonValue["PersistentRegionNumberLimit"] = *value;
306 }
307 else if (property.first == "SpareDeviceCount")
308 {
309 const uint64_t* value = std::get_if<uint64_t>(&property.second);
310 if (value == nullptr)
James Feistc50e7c62020-07-27 15:39:36 -0700311 {
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800312 messages::internalError(aResp->res);
313 return;
James Feistc50e7c62020-07-27 15:39:36 -0700314 }
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800315 aResp->res.jsonValue["SpareDeviceCount"] = *value;
316 }
317 else if (property.first == "IsSpareDeviceInUse")
318 {
319 const bool* value = std::get_if<bool>(&property.second);
320 if (value == nullptr)
James Feistc50e7c62020-07-27 15:39:36 -0700321 {
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800322 messages::internalError(aResp->res);
323 return;
James Feistc50e7c62020-07-27 15:39:36 -0700324 }
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800325 aResp->res.jsonValue["IsSpareDeviceEnabled"] = *value;
326 }
327 else if (property.first == "IsRankSpareEnabled")
328 {
329 const bool* value = std::get_if<bool>(&property.second);
330 if (value == nullptr)
James Feistc50e7c62020-07-27 15:39:36 -0700331 {
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800332 messages::internalError(aResp->res);
333 return;
James Feistc50e7c62020-07-27 15:39:36 -0700334 }
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800335 aResp->res.jsonValue["IsRankSpareEnabled"] = *value;
336 }
337 else if (property.first == "MaxAveragePowerLimitmW")
338 {
339 const auto* value =
340 std::get_if<std::vector<uint32_t>>(&property.second);
341 if (value == nullptr)
James Feistc50e7c62020-07-27 15:39:36 -0700342 {
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800343 messages::internalError(aResp->res);
344 BMCWEB_LOG_DEBUG
345 << "Invalid property type for MaxAveragePowerLimitmW";
346 return;
James Feistc50e7c62020-07-27 15:39:36 -0700347 }
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800348 aResp->res.jsonValue["MaxTDPMilliWatts"] = *value;
349 }
350 else if (property.first == "ConfigurationLocked")
351 {
352 const bool* value = std::get_if<bool>(&property.second);
353 if (value == nullptr)
James Feistc50e7c62020-07-27 15:39:36 -0700354 {
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800355 messages::internalError(aResp->res);
356 return;
357 }
358 aResp->res.jsonValue["ConfigurationLocked"] = *value;
359 }
360 else if (property.first == "AllowedMemoryModes")
361 {
362 const std::string* value = std::get_if<std::string>(&property.second);
363 if (value == nullptr)
364 {
365 messages::internalError(aResp->res);
366 BMCWEB_LOG_DEBUG << "Invalid property type for FormFactor";
367 return;
368 }
369 constexpr const std::array<const char*, 3> values{"Volatile", "PMEM",
370 "Block"};
James Feistc50e7c62020-07-27 15:39:36 -0700371
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800372 for (const char* v : values)
373 {
374 if (boost::ends_with(*value, v))
James Feistc50e7c62020-07-27 15:39:36 -0700375 {
Jiaqing Zhao1e04f3b2022-03-18 17:24:32 +0800376 aResp->res.jsonValue["OperatingMemoryModes"].push_back(v);
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800377 break;
James Feistc50e7c62020-07-27 15:39:36 -0700378 }
379 }
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800380 }
381 else if (property.first == "MemoryMedia")
382 {
383 const std::string* value = std::get_if<std::string>(&property.second);
384 if (value == nullptr)
James Feistc50e7c62020-07-27 15:39:36 -0700385 {
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800386 messages::internalError(aResp->res);
387 BMCWEB_LOG_DEBUG << "Invalid property type for MemoryMedia";
388 return;
389 }
390 constexpr const std::array<const char*, 3> values{"DRAM", "NAND",
391 "Intel3DXPoint"};
James Feistc50e7c62020-07-27 15:39:36 -0700392
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800393 for (const char* v : values)
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700394 {
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800395 if (boost::ends_with(*value, v))
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700396 {
Jiaqing Zhao1e04f3b2022-03-18 17:24:32 +0800397 aResp->res.jsonValue["MemoryMedia"].push_back(v);
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800398 break;
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700399 }
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700400 }
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800401 }
402 // PersistantMemory.SecurityCapabilites interface
403 else if (property.first == "ConfigurationLockCapable" ||
404 property.first == "DataLockCapable" ||
405 property.first == "PassphraseCapable")
406 {
407 const bool* value = std::get_if<bool>(&property.second);
408 if (value == nullptr)
James Feistc50e7c62020-07-27 15:39:36 -0700409 {
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800410 messages::internalError(aResp->res);
411 return;
James Feistc50e7c62020-07-27 15:39:36 -0700412 }
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800413 aResp->res.jsonValue["SecurityCapabilities"][property.first] = *value;
414 }
415 else if (property.first == "MaxPassphraseCount" ||
416 property.first == "PassphraseLockLimit")
417 {
418 const uint64_t* value = std::get_if<uint64_t>(&property.second);
419 if (value == nullptr)
420 {
421 messages::internalError(aResp->res);
422 return;
423 }
424 aResp->res.jsonValue["SecurityCapabilities"][property.first] = *value;
James Feistc50e7c62020-07-27 15:39:36 -0700425 }
426}
427
zhanghch058d1b46d2021-04-01 11:18:24 +0800428inline void getDimmDataByService(std::shared_ptr<bmcweb::AsyncResp> aResp,
Ed Tanous80789c82020-08-19 09:19:09 -0700429 const std::string& dimmId,
430 const std::string& service,
431 const std::string& objPath)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200432{
James Feist35e257a2020-06-05 13:30:51 -0700433 auto health = std::make_shared<HealthPopulate>(aResp);
434 health->selfPath = objPath;
435 health->populate();
436
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200437 BMCWEB_LOG_DEBUG << "Get available system components.";
438 crow::connections::systemBus->async_method_call(
Ed Tanousb9d36b42022-02-26 21:42:46 -0800439 [dimmId, aResp{std::move(aResp)}](
440 const boost::system::error_code ec,
441 const dbus::utility::DBusPropertiesMap& properties) {
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200442 if (ec)
443 {
444 BMCWEB_LOG_DEBUG << "DBUS response error";
445 messages::internalError(aResp->res);
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200446 return;
447 }
448 aResp->res.jsonValue["Id"] = dimmId;
449 aResp->res.jsonValue["Name"] = "DIMM Slot";
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200450 aResp->res.jsonValue["Status"]["State"] = "Enabled";
451 aResp->res.jsonValue["Status"]["Health"] = "OK";
452
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500453 for (const auto& property : properties)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200454 {
455 if (property.first == "MemoryDataWidth")
456 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700457 const uint16_t* value =
458 std::get_if<uint16_t>(&property.second);
459 if (value == nullptr)
460 {
461 continue;
462 }
463 aResp->res.jsonValue["DataWidthBits"] = *value;
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200464 }
Ed Tanousb9d36b42022-02-26 21:42:46 -0800465 else if (property.first == "MemorySizeInKB")
466 {
467 const uint32_t* memorySize =
468 std::get_if<uint32_t>(&property.second);
469 if (memorySize == nullptr)
470 {
471 // Important property not in desired type
472 messages::internalError(aResp->res);
473 return;
474 }
475 aResp->res.jsonValue["CapacityMiB"] = (*memorySize >> 10);
476 }
Manojkiran Eda7e236ca2019-06-25 23:06:32 +0530477 else if (property.first == "PartNumber")
478 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700479 const std::string* value =
480 std::get_if<std::string>(&property.second);
481 if (value == nullptr)
482 {
483 continue;
484 }
485 aResp->res.jsonValue["PartNumber"] = *value;
Manojkiran Eda7e236ca2019-06-25 23:06:32 +0530486 }
487 else if (property.first == "SerialNumber")
488 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700489 const std::string* value =
490 std::get_if<std::string>(&property.second);
491 if (value == nullptr)
492 {
493 continue;
494 }
495 aResp->res.jsonValue["SerialNumber"] = *value;
Manojkiran Eda7e236ca2019-06-25 23:06:32 +0530496 }
497 else if (property.first == "Manufacturer")
498 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700499 const std::string* value =
500 std::get_if<std::string>(&property.second);
501 if (value == nullptr)
502 {
503 continue;
504 }
505 aResp->res.jsonValue["Manufacturer"] = *value;
Manojkiran Eda7e236ca2019-06-25 23:06:32 +0530506 }
James Feistc50e7c62020-07-27 15:39:36 -0700507 else if (property.first == "RevisionCode")
508 {
509 const uint16_t* value =
510 std::get_if<uint16_t>(&property.second);
511
512 if (value == nullptr)
513 {
514 messages::internalError(aResp->res);
515 BMCWEB_LOG_DEBUG
516 << "Invalid property type for RevisionCode";
Chicago Duan601af5e2021-04-15 16:59:25 +0800517 return;
James Feistc50e7c62020-07-27 15:39:36 -0700518 }
519 aResp->res.jsonValue["FirmwareRevision"] =
520 std::to_string(*value);
521 }
Joshi-Mansi9a128eb2021-03-19 03:30:17 +0530522 else if (property.first == "Present")
523 {
524 const bool* value = std::get_if<bool>(&property.second);
525 if (value == nullptr)
526 {
527 messages::internalError(aResp->res);
528 BMCWEB_LOG_DEBUG
529 << "Invalid property type for Dimm Presence";
530 return;
531 }
Ed Tanouse05aec52022-01-25 10:28:56 -0800532 if (!*value)
Joshi-Mansi9a128eb2021-03-19 03:30:17 +0530533 {
534 aResp->res.jsonValue["Status"]["State"] = "Absent";
535 }
536 }
James Feistc50e7c62020-07-27 15:39:36 -0700537 else if (property.first == "MemoryTotalWidth")
538 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700539 const uint16_t* value =
540 std::get_if<uint16_t>(&property.second);
541 if (value == nullptr)
542 {
543 continue;
544 }
545 aResp->res.jsonValue["BusWidthBits"] = *value;
James Feistc50e7c62020-07-27 15:39:36 -0700546 }
547 else if (property.first == "ECC")
548 {
549 const std::string* value =
550 std::get_if<std::string>(&property.second);
551 if (value == nullptr)
552 {
553 messages::internalError(aResp->res);
554 BMCWEB_LOG_DEBUG << "Invalid property type for ECC";
Chicago Duan601af5e2021-04-15 16:59:25 +0800555 return;
James Feistc50e7c62020-07-27 15:39:36 -0700556 }
557 constexpr const std::array<const char*, 4> values{
558 "NoECC", "SingleBitECC", "MultiBitECC",
559 "AddressParity"};
560
561 for (const char* v : values)
562 {
563 if (boost::ends_with(*value, v))
564 {
565 aResp->res.jsonValue["ErrorCorrection"] = v;
566 break;
567 }
568 }
569 }
570 else if (property.first == "FormFactor")
571 {
572 const std::string* value =
573 std::get_if<std::string>(&property.second);
574 if (value == nullptr)
575 {
576 messages::internalError(aResp->res);
577 BMCWEB_LOG_DEBUG
578 << "Invalid property type for FormFactor";
Chicago Duan601af5e2021-04-15 16:59:25 +0800579 return;
James Feistc50e7c62020-07-27 15:39:36 -0700580 }
581 constexpr const std::array<const char*, 11> values{
582 "RDIMM", "UDIMM", "SO_DIMM",
583 "LRDIMM", "Mini_RDIMM", "Mini_UDIMM",
584 "SO_RDIMM_72b", "SO_UDIMM_72b", "SO_DIMM_16b",
585 "SO_DIMM_32b", "Die"};
586
587 for (const char* v : values)
588 {
589 if (boost::ends_with(*value, v))
590 {
591 aResp->res.jsonValue["BaseModuleType"] = v;
592 break;
593 }
594 }
595 }
596 else if (property.first == "AllowedSpeedsMT")
597 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700598 const std::vector<uint16_t>* value =
599 std::get_if<std::vector<uint16_t>>(&property.second);
600 if (value == nullptr)
601 {
602 continue;
603 }
604 nlohmann::json& jValue =
605 aResp->res.jsonValue["AllowedSpeedsMHz"];
606 jValue = nlohmann::json::array();
607 for (uint16_t subVal : *value)
608 {
609 jValue.push_back(subVal);
610 }
James Feistc50e7c62020-07-27 15:39:36 -0700611 }
612 else if (property.first == "MemoryAttributes")
613 {
614 const uint8_t* value =
615 std::get_if<uint8_t>(&property.second);
616
617 if (value == nullptr)
618 {
619 messages::internalError(aResp->res);
620 BMCWEB_LOG_DEBUG
621 << "Invalid property type for MemoryAttributes";
Chicago Duan601af5e2021-04-15 16:59:25 +0800622 return;
James Feistc50e7c62020-07-27 15:39:36 -0700623 }
624 aResp->res.jsonValue["RankCount"] =
625 static_cast<uint64_t>(*value);
626 }
627 else if (property.first == "MemoryConfiguredSpeedInMhz")
628 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700629 const uint16_t* value =
630 std::get_if<uint16_t>(&property.second);
631 if (value == nullptr)
632 {
633 continue;
634 }
635 aResp->res.jsonValue["OperatingSpeedMhz"] = *value;
James Feistc50e7c62020-07-27 15:39:36 -0700636 }
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200637 else if (property.first == "MemoryType")
638 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500639 const auto* value =
Ed Tanousabf2add2019-01-22 16:40:12 -0800640 std::get_if<std::string>(&property.second);
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200641 if (value != nullptr)
642 {
Gunnar Mills313efb12020-10-26 16:05:08 -0500643 std::string memoryDeviceType =
644 translateMemoryTypeToRedfish(*value);
645 // Values like "Unknown" or "Other" will return empty
646 // so just leave off
647 if (!memoryDeviceType.empty())
James Feistc50e7c62020-07-27 15:39:36 -0700648 {
Gunnar Mills313efb12020-10-26 16:05:08 -0500649 aResp->res.jsonValue["MemoryDeviceType"] =
650 memoryDeviceType;
James Feistc50e7c62020-07-27 15:39:36 -0700651 }
James Feistc50e7c62020-07-27 15:39:36 -0700652 if (value->find("DDR") != std::string::npos)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200653 {
654 aResp->res.jsonValue["MemoryType"] = "DRAM";
655 }
James Feistc50e7c62020-07-27 15:39:36 -0700656 else if (boost::ends_with(*value, "Logical"))
657 {
658 aResp->res.jsonValue["MemoryType"] = "IntelOptane";
659 }
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200660 }
661 }
James Feistc50e7c62020-07-27 15:39:36 -0700662 // memory location interface
663 else if (property.first == "Channel" ||
664 property.first == "MemoryController" ||
665 property.first == "Slot" || property.first == "Socket")
666 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700667 const std::string* value =
668 std::get_if<std::string>(&property.second);
669 if (value == nullptr)
670 {
671 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +0800672 return;
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700673 }
James Feistc50e7c62020-07-27 15:39:36 -0700674 aResp->res.jsonValue["MemoryLocation"][property.first] =
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700675 *value;
James Feistc50e7c62020-07-27 15:39:36 -0700676 }
SunnySrivastava1984ee135e22020-12-15 12:42:19 -0600677 else if (property.first == "SparePartNumber")
678 {
679 const std::string* value =
680 std::get_if<std::string>(&property.second);
681 if (value == nullptr)
682 {
683 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +0800684 return;
SunnySrivastava1984ee135e22020-12-15 12:42:19 -0600685 }
686 aResp->res.jsonValue["SparePartNumber"] = *value;
687 }
688 else if (property.first == "Model")
689 {
690 const std::string* value =
691 std::get_if<std::string>(&property.second);
692 if (value == nullptr)
693 {
694 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +0800695 return;
SunnySrivastava1984ee135e22020-12-15 12:42:19 -0600696 }
697 aResp->res.jsonValue["Model"] = *value;
698 }
699 else if (property.first == "LocationCode")
700 {
701 const std::string* value =
702 std::get_if<std::string>(&property.second);
703 if (value == nullptr)
704 {
705 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +0800706 return;
SunnySrivastava1984ee135e22020-12-15 12:42:19 -0600707 }
708 aResp->res
709 .jsonValue["Location"]["PartLocation"]["ServiceLabel"] =
710 *value;
711 }
James Feistc50e7c62020-07-27 15:39:36 -0700712 else
713 {
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800714 getPersistentMemoryProperties(aResp, property);
James Feistc50e7c62020-07-27 15:39:36 -0700715 }
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200716 }
717 },
718 service, objPath, "org.freedesktop.DBus.Properties", "GetAll", "");
719}
720
zhanghch058d1b46d2021-04-01 11:18:24 +0800721inline void getDimmPartitionData(std::shared_ptr<bmcweb::AsyncResp> aResp,
Ed Tanous23a21a12020-07-25 04:45:05 +0000722 const std::string& service,
723 const std::string& path)
James Feist45094ad2020-04-29 14:02:30 -0700724{
725 crow::connections::systemBus->async_method_call(
726 [aResp{std::move(aResp)}](
727 const boost::system::error_code ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -0800728 const dbus::utility::DBusPropertiesMap& properties) {
James Feist45094ad2020-04-29 14:02:30 -0700729 if (ec)
730 {
731 BMCWEB_LOG_DEBUG << "DBUS response error";
732 messages::internalError(aResp->res);
733
734 return;
735 }
736
737 nlohmann::json& partition =
738 aResp->res.jsonValue["Regions"].emplace_back(
739 nlohmann::json::object());
740 for (const auto& [key, val] : properties)
741 {
742 if (key == "MemoryClassification")
743 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700744 const std::string* value = std::get_if<std::string>(&val);
745 if (value == nullptr)
746 {
747 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +0800748 return;
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700749 }
750 partition[key] = *value;
James Feist45094ad2020-04-29 14:02:30 -0700751 }
752 else if (key == "OffsetInKiB")
753 {
754 const uint64_t* value = std::get_if<uint64_t>(&val);
755 if (value == nullptr)
756 {
757 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +0800758 return;
James Feist45094ad2020-04-29 14:02:30 -0700759 }
760
761 partition["OffsetMiB"] = (*value >> 10);
762 }
763 else if (key == "PartitionId")
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["RegionId"] = *value;
James Feist45094ad2020-04-29 14:02:30 -0700772 }
773
774 else if (key == "PassphraseState")
775 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700776 const bool* value = std::get_if<bool>(&val);
777 if (value == nullptr)
778 {
779 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +0800780 return;
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700781 }
782 partition["PassphraseEnabled"] = *value;
James Feist45094ad2020-04-29 14:02:30 -0700783 }
784 else if (key == "SizeInKiB")
785 {
786 const uint64_t* value = std::get_if<uint64_t>(&val);
787 if (value == nullptr)
788 {
789 messages::internalError(aResp->res);
790 BMCWEB_LOG_DEBUG
791 << "Invalid property type for SizeInKiB";
Chicago Duan601af5e2021-04-15 16:59:25 +0800792 return;
James Feist45094ad2020-04-29 14:02:30 -0700793 }
794 partition["SizeMiB"] = (*value >> 10);
795 }
796 }
797 },
798
799 service, path, "org.freedesktop.DBus.Properties", "GetAll",
800 "xyz.openbmc_project.Inventory.Item.PersistentMemory.Partition");
801}
802
zhanghch058d1b46d2021-04-01 11:18:24 +0800803inline void getDimmData(std::shared_ptr<bmcweb::AsyncResp> aResp,
Ed Tanous23a21a12020-07-25 04:45:05 +0000804 const std::string& dimmId)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200805{
806 BMCWEB_LOG_DEBUG << "Get available system dimm resources.";
807 crow::connections::systemBus->async_method_call(
Ed Tanous029573d2019-02-01 10:57:49 -0800808 [dimmId, aResp{std::move(aResp)}](
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200809 const boost::system::error_code ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -0800810 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200811 if (ec)
812 {
813 BMCWEB_LOG_DEBUG << "DBUS response error";
814 messages::internalError(aResp->res);
815
816 return;
817 }
James Feist45094ad2020-04-29 14:02:30 -0700818 bool found = false;
819 for (const auto& [path, object] : subtree)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200820 {
James Feist45094ad2020-04-29 14:02:30 -0700821 if (path.find(dimmId) != std::string::npos)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200822 {
James Feist45094ad2020-04-29 14:02:30 -0700823 for (const auto& [service, interfaces] : object)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200824 {
Ed Tanousb9d36b42022-02-26 21:42:46 -0800825 for (const auto& interface : interfaces)
James Feist45094ad2020-04-29 14:02:30 -0700826 {
Ed Tanousb9d36b42022-02-26 21:42:46 -0800827 if (interface ==
828 "xyz.openbmc_project.Inventory.Item.Dimm")
829 {
830 getDimmDataByService(aResp, dimmId, service,
831 path);
832 found = true;
833 }
James Feist45094ad2020-04-29 14:02:30 -0700834
Ed Tanousb9d36b42022-02-26 21:42:46 -0800835 // partitions are separate as there can be multiple
836 // per
837 // device, i.e.
838 // /xyz/openbmc_project/Inventory/Item/Dimm1/Partition1
839 // /xyz/openbmc_project/Inventory/Item/Dimm1/Partition2
840 if (interface ==
841 "xyz.openbmc_project.Inventory.Item.PersistentMemory.Partition")
842 {
843 getDimmPartitionData(aResp, service, path);
844 }
James Feist45094ad2020-04-29 14:02:30 -0700845 }
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200846 }
847 }
848 }
849 // Object not found
James Feist45094ad2020-04-29 14:02:30 -0700850 if (!found)
851 {
852 messages::resourceNotFound(aResp->res, "Memory", dimmId);
853 }
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200854 return;
855 },
856 "xyz.openbmc_project.ObjectMapper",
857 "/xyz/openbmc_project/object_mapper",
858 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
Ed Tanous271584a2019-07-09 16:24:22 -0700859 "/xyz/openbmc_project/inventory", 0,
James Feist45094ad2020-04-29 14:02:30 -0700860 std::array<const char*, 2>{
861 "xyz.openbmc_project.Inventory.Item.Dimm",
862 "xyz.openbmc_project.Inventory.Item.PersistentMemory.Partition"});
Ed Tanous271584a2019-07-09 16:24:22 -0700863}
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200864
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700865inline void requestRoutesMemoryCollection(App& app)
Ed Tanous029573d2019-02-01 10:57:49 -0800866{
Ed Tanous029573d2019-02-01 10:57:49 -0800867 /**
868 * Functions triggers appropriate requests on DBus
869 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700870 BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/Memory/")
Ed Tanoused398212021-06-09 17:05:54 -0700871 .privileges(redfish::privileges::getMemoryCollection)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700872 .methods(boost::beast::http::verb::get)(
873 [](const crow::Request&,
874 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
875 asyncResp->res.jsonValue["@odata.type"] =
876 "#MemoryCollection.MemoryCollection";
877 asyncResp->res.jsonValue["Name"] = "Memory Module Collection";
878 asyncResp->res.jsonValue["@odata.id"] =
879 "/redfish/v1/Systems/system/Memory";
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200880
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700881 collection_util::getCollectionMembers(
882 asyncResp, "/redfish/v1/Systems/system/Memory",
883 {"xyz.openbmc_project.Inventory.Item.Dimm"});
884 });
885}
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200886
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700887inline void requestRoutesMemory(App& app)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200888{
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200889 /**
890 * Functions triggers appropriate requests on DBus
891 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700892 BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/Memory/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -0700893 .privileges(redfish::privileges::getMemory)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700894 .methods(boost::beast::http::verb::get)(
895 [](const crow::Request&,
896 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
897 const std::string& dimmId) {
898 asyncResp->res.jsonValue["@odata.type"] =
899 "#Memory.v1_11_0.Memory";
900 asyncResp->res.jsonValue["@odata.id"] =
901 "/redfish/v1/Systems/system/Memory/" + dimmId;
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200902
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700903 getDimmData(asyncResp, dimmId);
904 });
905}
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200906
907} // namespace redfish