blob: 73d739a1640494c3156fa92475d1a07b21262dc6 [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 Tanous168e20c2021-12-13 14:39:53 -080022#include <dbus_utility.hpp>
Ed Tanoused398212021-06-09 17:05:54 -070023#include <registries/privilege_registry.hpp>
Gunnar Mills116bcc52020-10-14 15:23:42 -050024#include <utils/collection.hpp>
Ed Tanousf201ffb2021-10-09 14:49:28 -070025#include <utils/hex_utils.hpp>
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +020026#include <utils/json_utils.hpp>
27
28namespace redfish
29{
30
Ed Tanous168e20c2021-12-13 14:39:53 -080031using DimmProperties =
32 boost::container::flat_map<std::string, dbus::utility::DbusVariantType>;
James Feistc50e7c62020-07-27 15:39:36 -070033
Gunnar Mills313efb12020-10-26 16:05:08 -050034inline std::string translateMemoryTypeToRedfish(const std::string& memoryType)
35{
36 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR")
37 {
38 return "DDR";
39 }
40 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR2")
41 {
42 return "DDR2";
43 }
44 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR3")
45 {
46 return "DDR3";
47 }
48 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR4")
49 {
50 return "DDR4";
51 }
52 if (memoryType ==
53 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR4E_SDRAM")
54 {
55 return "DDR4E_SDRAM";
56 }
Mansi Joshi11a2f0f2021-07-19 14:33:27 +053057 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR5")
58 {
59 return "DDR5";
60 }
Gunnar Mills313efb12020-10-26 16:05:08 -050061 if (memoryType ==
62 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.LPDDR4_SDRAM")
63 {
64 return "LPDDR4_SDRAM";
65 }
66 if (memoryType ==
67 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.LPDDR3_SDRAM")
68 {
69 return "LPDDR3_SDRAM";
70 }
71 if (memoryType ==
72 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR2_SDRAM_FB_DIMM")
73 {
74 return "DDR2_SDRAM_FB_DIMM";
75 }
George Liu0fda0f12021-11-16 10:06:17 +080076 if (memoryType ==
77 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR2_SDRAM_FB_DIMM_PROB")
Gunnar Mills313efb12020-10-26 16:05:08 -050078 {
79 return "DDR2_SDRAM_FB_DIMM_PROBE";
80 }
81 if (memoryType ==
82 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR_SGRAM")
83 {
84 return "DDR_SGRAM";
85 }
86 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.ROM")
87 {
88 return "ROM";
89 }
90 if (memoryType ==
91 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.SDRAM")
92 {
93 return "SDRAM";
94 }
95 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.EDO")
96 {
97 return "EDO";
98 }
99 if (memoryType ==
100 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.FastPageMode")
101 {
102 return "FastPageMode";
103 }
104 if (memoryType ==
105 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.PipelinedNibble")
106 {
107 return "PipelinedNibble";
108 }
109 if (memoryType ==
110 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.Logical")
111 {
112 return "Logical";
113 }
114 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.HBM")
115 {
116 return "HBM";
117 }
118 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.HBM2")
119 {
120 return "HBM2";
121 }
122 // This is values like Other or Unknown
123 // Also D-Bus values:
124 // DRAM
125 // EDRAM
126 // VRAM
127 // SRAM
128 // RAM
129 // FLASH
130 // EEPROM
131 // FEPROM
132 // EPROM
133 // CDRAM
134 // ThreeDRAM
135 // RDRAM
136 // FBD2
137 // LPDDR_SDRAM
138 // LPDDR2_SDRAM
Mansi Joshi11a2f0f2021-07-19 14:33:27 +0530139 // LPDDR5_SDRAM
Gunnar Mills313efb12020-10-26 16:05:08 -0500140 return "";
141}
142
Ed Tanous168e20c2021-12-13 14:39:53 -0800143inline void dimmPropToHex(
144 const std::shared_ptr<bmcweb::AsyncResp>& aResp, const char* key,
145 const std::pair<std::string, dbus::utility::DbusVariantType>& property)
James Feistc50e7c62020-07-27 15:39:36 -0700146{
147 const uint16_t* value = std::get_if<uint16_t>(&property.second);
148 if (value == nullptr)
149 {
150 messages::internalError(aResp->res);
151 BMCWEB_LOG_DEBUG << "Invalid property type for " << property.first;
152 return;
153 }
154
Ed Tanous866e4862022-02-17 11:40:25 -0800155 aResp->res.jsonValue[key] = "0x" + intToHexString(*value, 4);
James Feistc50e7c62020-07-27 15:39:36 -0700156}
157
zhanghch058d1b46d2021-04-01 11:18:24 +0800158inline void getPersistentMemoryProperties(
159 const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800160 const std::pair<std::string, dbus::utility::DbusVariantType>& property)
James Feistc50e7c62020-07-27 15:39:36 -0700161{
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800162 if (property.first == "ModuleManufacturerID")
James Feistc50e7c62020-07-27 15:39:36 -0700163 {
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800164 dimmPropToHex(aResp, "ModuleManufacturerID", property);
165 }
166 else if (property.first == "ModuleProductID")
167 {
168 dimmPropToHex(aResp, "ModuleProductID", property);
169 }
170 else if (property.first == "SubsystemVendorID")
171 {
172 dimmPropToHex(aResp, "MemorySubsystemControllerManufacturerID",
173 property);
174 }
175 else if (property.first == "SubsystemDeviceID")
176 {
177 dimmPropToHex(aResp, "MemorySubsystemControllerProductID", property);
178 }
179 else if (property.first == "VolatileRegionSizeLimitInKiB")
180 {
181 const uint64_t* value = std::get_if<uint64_t>(&property.second);
James Feistc50e7c62020-07-27 15:39:36 -0700182
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800183 if (value == nullptr)
James Feistc50e7c62020-07-27 15:39:36 -0700184 {
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800185 messages::internalError(aResp->res);
186 BMCWEB_LOG_DEBUG
187 << "Invalid property type for VolatileRegionSizeLimitKiB";
188 return;
189 }
190 aResp->res.jsonValue["VolatileRegionSizeLimitMiB"] = (*value) >> 10;
191 }
192 else if (property.first == "PmRegionSizeLimitInKiB")
193 {
194 const uint64_t* value = std::get_if<uint64_t>(&property.second);
James Feistc50e7c62020-07-27 15:39:36 -0700195
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800196 if (value == nullptr)
James Feistc50e7c62020-07-27 15:39:36 -0700197 {
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800198 messages::internalError(aResp->res);
199 BMCWEB_LOG_DEBUG << "Invalid property type for PmRegioSizeLimitKiB";
200 return;
201 }
202 aResp->res.jsonValue["PersistentRegionSizeLimitMiB"] = (*value) >> 10;
203 }
204 else if (property.first == "VolatileSizeInKiB")
205 {
206 const uint64_t* value = std::get_if<uint64_t>(&property.second);
James Feistc50e7c62020-07-27 15:39:36 -0700207
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800208 if (value == nullptr)
James Feistc50e7c62020-07-27 15:39:36 -0700209 {
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800210 messages::internalError(aResp->res);
211 BMCWEB_LOG_DEBUG << "Invalid property type for VolatileSizeInKiB";
212 return;
James Feistc50e7c62020-07-27 15:39:36 -0700213 }
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800214 aResp->res.jsonValue["VolatileSizeMiB"] = (*value) >> 10;
215 }
216 else if (property.first == "PmSizeInKiB")
217 {
218 const uint64_t* value = std::get_if<uint64_t>(&property.second);
219 if (value == nullptr)
James Feistc50e7c62020-07-27 15:39:36 -0700220 {
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800221 messages::internalError(aResp->res);
222 BMCWEB_LOG_DEBUG << "Invalid property type for PmSizeInKiB";
223 return;
James Feistc50e7c62020-07-27 15:39:36 -0700224 }
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800225 aResp->res.jsonValue["NonVolatileSizeMiB"] = (*value) >> 10;
226 }
227 else if (property.first == "CacheSizeInKB")
228 {
229 const uint64_t* value = std::get_if<uint64_t>(&property.second);
230 if (value == nullptr)
231 {
232 messages::internalError(aResp->res);
233 BMCWEB_LOG_DEBUG << "Invalid property type for CacheSizeInKB";
234 return;
235 }
236 aResp->res.jsonValue["CacheSizeMiB"] = (*value >> 10);
237 }
James Feistc50e7c62020-07-27 15:39:36 -0700238
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800239 else if (property.first == "VoltaileRegionMaxSizeInKib")
240 {
241 const uint64_t* value = std::get_if<uint64_t>(&property.second);
James Feistc50e7c62020-07-27 15:39:36 -0700242
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800243 if (value == nullptr)
James Feistc50e7c62020-07-27 15:39:36 -0700244 {
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800245 messages::internalError(aResp->res);
246 BMCWEB_LOG_DEBUG
247 << "Invalid property type for VolatileRegionMaxSizeInKib";
248 return;
249 }
250 aResp->res.jsonValue["VolatileRegionSizeMaxMiB"] = (*value) >> 10;
251 }
252 else if (property.first == "PmRegionMaxSizeInKiB")
253 {
254 const uint64_t* value = std::get_if<uint64_t>(&property.second);
James Feistc50e7c62020-07-27 15:39:36 -0700255
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800256 if (value == nullptr)
James Feistc50e7c62020-07-27 15:39:36 -0700257 {
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800258 messages::internalError(aResp->res);
259 BMCWEB_LOG_DEBUG
260 << "Invalid property type for PmRegionMaxSizeInKiB";
261 return;
262 }
263 aResp->res.jsonValue["PersistentRegionSizeMaxMiB"] = (*value) >> 10;
264 }
265 else if (property.first == "AllocationIncrementInKiB")
266 {
267 const uint64_t* value = std::get_if<uint64_t>(&property.second);
James Feistc50e7c62020-07-27 15:39:36 -0700268
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800269 if (value == nullptr)
James Feistc50e7c62020-07-27 15:39:36 -0700270 {
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800271 messages::internalError(aResp->res);
272 BMCWEB_LOG_DEBUG
273 << "Invalid property type for AllocationIncrementInKiB";
274 return;
275 }
276 aResp->res.jsonValue["AllocationIncrementMiB"] = (*value) >> 10;
277 }
278 else if (property.first == "AllocationAlignmentInKiB")
279 {
280 const uint64_t* value = std::get_if<uint64_t>(&property.second);
James Feistc50e7c62020-07-27 15:39:36 -0700281
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800282 if (value == nullptr)
James Feistc50e7c62020-07-27 15:39:36 -0700283 {
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800284 messages::internalError(aResp->res);
285 BMCWEB_LOG_DEBUG
286 << "Invalid property type for AllocationAlignmentInKiB";
287 return;
James Feistc50e7c62020-07-27 15:39:36 -0700288 }
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800289 aResp->res.jsonValue["AllocationAlignmentMiB"] = (*value) >> 10;
290 }
291 else if (property.first == "VolatileRegionNumberLimit")
292 {
293 const uint64_t* value = std::get_if<uint64_t>(&property.second);
294 if (value == nullptr)
James Feistc50e7c62020-07-27 15:39:36 -0700295 {
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800296 messages::internalError(aResp->res);
297 return;
James Feistc50e7c62020-07-27 15:39:36 -0700298 }
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800299 aResp->res.jsonValue["VolatileRegionNumberLimit"] = *value;
300 }
301 else if (property.first == "PmRegionNumberLimit")
302 {
303 const uint64_t* value = std::get_if<uint64_t>(&property.second);
304 if (value == nullptr)
James Feistc50e7c62020-07-27 15:39:36 -0700305 {
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800306 messages::internalError(aResp->res);
307 return;
James Feistc50e7c62020-07-27 15:39:36 -0700308 }
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800309 aResp->res.jsonValue["PersistentRegionNumberLimit"] = *value;
310 }
311 else if (property.first == "SpareDeviceCount")
312 {
313 const uint64_t* value = std::get_if<uint64_t>(&property.second);
314 if (value == nullptr)
James Feistc50e7c62020-07-27 15:39:36 -0700315 {
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800316 messages::internalError(aResp->res);
317 return;
James Feistc50e7c62020-07-27 15:39:36 -0700318 }
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800319 aResp->res.jsonValue["SpareDeviceCount"] = *value;
320 }
321 else if (property.first == "IsSpareDeviceInUse")
322 {
323 const bool* value = std::get_if<bool>(&property.second);
324 if (value == nullptr)
James Feistc50e7c62020-07-27 15:39:36 -0700325 {
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800326 messages::internalError(aResp->res);
327 return;
James Feistc50e7c62020-07-27 15:39:36 -0700328 }
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800329 aResp->res.jsonValue["IsSpareDeviceEnabled"] = *value;
330 }
331 else if (property.first == "IsRankSpareEnabled")
332 {
333 const bool* value = std::get_if<bool>(&property.second);
334 if (value == nullptr)
James Feistc50e7c62020-07-27 15:39:36 -0700335 {
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800336 messages::internalError(aResp->res);
337 return;
James Feistc50e7c62020-07-27 15:39:36 -0700338 }
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800339 aResp->res.jsonValue["IsRankSpareEnabled"] = *value;
340 }
341 else if (property.first == "MaxAveragePowerLimitmW")
342 {
343 const auto* value =
344 std::get_if<std::vector<uint32_t>>(&property.second);
345 if (value == nullptr)
James Feistc50e7c62020-07-27 15:39:36 -0700346 {
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800347 messages::internalError(aResp->res);
348 BMCWEB_LOG_DEBUG
349 << "Invalid property type for MaxAveragePowerLimitmW";
350 return;
James Feistc50e7c62020-07-27 15:39:36 -0700351 }
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800352 aResp->res.jsonValue["MaxTDPMilliWatts"] = *value;
353 }
354 else if (property.first == "ConfigurationLocked")
355 {
356 const bool* value = std::get_if<bool>(&property.second);
357 if (value == nullptr)
James Feistc50e7c62020-07-27 15:39:36 -0700358 {
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800359 messages::internalError(aResp->res);
360 return;
361 }
362 aResp->res.jsonValue["ConfigurationLocked"] = *value;
363 }
364 else if (property.first == "AllowedMemoryModes")
365 {
366 const std::string* value = std::get_if<std::string>(&property.second);
367 if (value == nullptr)
368 {
369 messages::internalError(aResp->res);
370 BMCWEB_LOG_DEBUG << "Invalid property type for FormFactor";
371 return;
372 }
373 constexpr const std::array<const char*, 3> values{"Volatile", "PMEM",
374 "Block"};
James Feistc50e7c62020-07-27 15:39:36 -0700375
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800376 for (const char* v : values)
377 {
378 if (boost::ends_with(*value, v))
James Feistc50e7c62020-07-27 15:39:36 -0700379 {
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800380 aResp->res.jsonValue["OperatingMemoryModes "] = v;
381 break;
James Feistc50e7c62020-07-27 15:39:36 -0700382 }
383 }
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800384 }
385 else if (property.first == "MemoryMedia")
386 {
387 const std::string* value = std::get_if<std::string>(&property.second);
388 if (value == nullptr)
James Feistc50e7c62020-07-27 15:39:36 -0700389 {
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800390 messages::internalError(aResp->res);
391 BMCWEB_LOG_DEBUG << "Invalid property type for MemoryMedia";
392 return;
393 }
394 constexpr const std::array<const char*, 3> values{"DRAM", "NAND",
395 "Intel3DXPoint"};
James Feistc50e7c62020-07-27 15:39:36 -0700396
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800397 for (const char* v : values)
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700398 {
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800399 if (boost::ends_with(*value, v))
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700400 {
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800401 aResp->res.jsonValue["MemoryMedia"] = v;
402 break;
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700403 }
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700404 }
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800405 }
406 // PersistantMemory.SecurityCapabilites interface
407 else if (property.first == "ConfigurationLockCapable" ||
408 property.first == "DataLockCapable" ||
409 property.first == "PassphraseCapable")
410 {
411 const bool* value = std::get_if<bool>(&property.second);
412 if (value == nullptr)
James Feistc50e7c62020-07-27 15:39:36 -0700413 {
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800414 messages::internalError(aResp->res);
415 return;
James Feistc50e7c62020-07-27 15:39:36 -0700416 }
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800417 aResp->res.jsonValue["SecurityCapabilities"][property.first] = *value;
418 }
419 else if (property.first == "MaxPassphraseCount" ||
420 property.first == "PassphraseLockLimit")
421 {
422 const uint64_t* value = std::get_if<uint64_t>(&property.second);
423 if (value == nullptr)
424 {
425 messages::internalError(aResp->res);
426 return;
427 }
428 aResp->res.jsonValue["SecurityCapabilities"][property.first] = *value;
James Feistc50e7c62020-07-27 15:39:36 -0700429 }
430}
431
zhanghch058d1b46d2021-04-01 11:18:24 +0800432inline void getDimmDataByService(std::shared_ptr<bmcweb::AsyncResp> aResp,
Ed Tanous80789c82020-08-19 09:19:09 -0700433 const std::string& dimmId,
434 const std::string& service,
435 const std::string& objPath)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200436{
James Feist35e257a2020-06-05 13:30:51 -0700437 auto health = std::make_shared<HealthPopulate>(aResp);
438 health->selfPath = objPath;
439 health->populate();
440
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200441 BMCWEB_LOG_DEBUG << "Get available system components.";
442 crow::connections::systemBus->async_method_call(
James Feistc50e7c62020-07-27 15:39:36 -0700443 [dimmId, aResp{std::move(aResp)}](const boost::system::error_code ec,
444 const DimmProperties& properties) {
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200445 if (ec)
446 {
447 BMCWEB_LOG_DEBUG << "DBUS response error";
448 messages::internalError(aResp->res);
449
450 return;
451 }
452 aResp->res.jsonValue["Id"] = dimmId;
453 aResp->res.jsonValue["Name"] = "DIMM Slot";
454
455 const auto memorySizeProperty = properties.find("MemorySizeInKB");
Gunnar Millsaceb7fc2018-12-10 15:17:20 -0600456 if (memorySizeProperty != properties.end())
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200457 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500458 const uint32_t* memorySize =
Ed Tanousabf2add2019-01-22 16:40:12 -0800459 std::get_if<uint32_t>(&memorySizeProperty->second);
Gunnar Millsaceb7fc2018-12-10 15:17:20 -0600460 if (memorySize == nullptr)
461 {
462 // Important property not in desired type
463 messages::internalError(aResp->res);
Gunnar Millsaceb7fc2018-12-10 15:17:20 -0600464 return;
465 }
466 aResp->res.jsonValue["CapacityMiB"] = (*memorySize >> 10);
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200467 }
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200468 aResp->res.jsonValue["Status"]["State"] = "Enabled";
469 aResp->res.jsonValue["Status"]["Health"] = "OK";
470
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500471 for (const auto& property : properties)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200472 {
473 if (property.first == "MemoryDataWidth")
474 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700475 const uint16_t* value =
476 std::get_if<uint16_t>(&property.second);
477 if (value == nullptr)
478 {
479 continue;
480 }
481 aResp->res.jsonValue["DataWidthBits"] = *value;
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200482 }
Manojkiran Eda7e236ca2019-06-25 23:06:32 +0530483 else if (property.first == "PartNumber")
484 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700485 const std::string* value =
486 std::get_if<std::string>(&property.second);
487 if (value == nullptr)
488 {
489 continue;
490 }
491 aResp->res.jsonValue["PartNumber"] = *value;
Manojkiran Eda7e236ca2019-06-25 23:06:32 +0530492 }
493 else if (property.first == "SerialNumber")
494 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700495 const std::string* value =
496 std::get_if<std::string>(&property.second);
497 if (value == nullptr)
498 {
499 continue;
500 }
501 aResp->res.jsonValue["SerialNumber"] = *value;
Manojkiran Eda7e236ca2019-06-25 23:06:32 +0530502 }
503 else if (property.first == "Manufacturer")
504 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700505 const std::string* value =
506 std::get_if<std::string>(&property.second);
507 if (value == nullptr)
508 {
509 continue;
510 }
511 aResp->res.jsonValue["Manufacturer"] = *value;
Manojkiran Eda7e236ca2019-06-25 23:06:32 +0530512 }
James Feistc50e7c62020-07-27 15:39:36 -0700513 else if (property.first == "RevisionCode")
514 {
515 const uint16_t* value =
516 std::get_if<uint16_t>(&property.second);
517
518 if (value == nullptr)
519 {
520 messages::internalError(aResp->res);
521 BMCWEB_LOG_DEBUG
522 << "Invalid property type for RevisionCode";
Chicago Duan601af5e2021-04-15 16:59:25 +0800523 return;
James Feistc50e7c62020-07-27 15:39:36 -0700524 }
525 aResp->res.jsonValue["FirmwareRevision"] =
526 std::to_string(*value);
527 }
Joshi-Mansi9a128eb2021-03-19 03:30:17 +0530528 else if (property.first == "Present")
529 {
530 const bool* value = std::get_if<bool>(&property.second);
531 if (value == nullptr)
532 {
533 messages::internalError(aResp->res);
534 BMCWEB_LOG_DEBUG
535 << "Invalid property type for Dimm Presence";
536 return;
537 }
Ed Tanouse05aec52022-01-25 10:28:56 -0800538 if (!*value)
Joshi-Mansi9a128eb2021-03-19 03:30:17 +0530539 {
540 aResp->res.jsonValue["Status"]["State"] = "Absent";
541 }
542 }
James Feistc50e7c62020-07-27 15:39:36 -0700543 else if (property.first == "MemoryTotalWidth")
544 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700545 const uint16_t* value =
546 std::get_if<uint16_t>(&property.second);
547 if (value == nullptr)
548 {
549 continue;
550 }
551 aResp->res.jsonValue["BusWidthBits"] = *value;
James Feistc50e7c62020-07-27 15:39:36 -0700552 }
553 else if (property.first == "ECC")
554 {
555 const std::string* value =
556 std::get_if<std::string>(&property.second);
557 if (value == nullptr)
558 {
559 messages::internalError(aResp->res);
560 BMCWEB_LOG_DEBUG << "Invalid property type for ECC";
Chicago Duan601af5e2021-04-15 16:59:25 +0800561 return;
James Feistc50e7c62020-07-27 15:39:36 -0700562 }
563 constexpr const std::array<const char*, 4> values{
564 "NoECC", "SingleBitECC", "MultiBitECC",
565 "AddressParity"};
566
567 for (const char* v : values)
568 {
569 if (boost::ends_with(*value, v))
570 {
571 aResp->res.jsonValue["ErrorCorrection"] = v;
572 break;
573 }
574 }
575 }
576 else if (property.first == "FormFactor")
577 {
578 const std::string* value =
579 std::get_if<std::string>(&property.second);
580 if (value == nullptr)
581 {
582 messages::internalError(aResp->res);
583 BMCWEB_LOG_DEBUG
584 << "Invalid property type for FormFactor";
Chicago Duan601af5e2021-04-15 16:59:25 +0800585 return;
James Feistc50e7c62020-07-27 15:39:36 -0700586 }
587 constexpr const std::array<const char*, 11> values{
588 "RDIMM", "UDIMM", "SO_DIMM",
589 "LRDIMM", "Mini_RDIMM", "Mini_UDIMM",
590 "SO_RDIMM_72b", "SO_UDIMM_72b", "SO_DIMM_16b",
591 "SO_DIMM_32b", "Die"};
592
593 for (const char* v : values)
594 {
595 if (boost::ends_with(*value, v))
596 {
597 aResp->res.jsonValue["BaseModuleType"] = v;
598 break;
599 }
600 }
601 }
602 else if (property.first == "AllowedSpeedsMT")
603 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700604 const std::vector<uint16_t>* value =
605 std::get_if<std::vector<uint16_t>>(&property.second);
606 if (value == nullptr)
607 {
608 continue;
609 }
610 nlohmann::json& jValue =
611 aResp->res.jsonValue["AllowedSpeedsMHz"];
612 jValue = nlohmann::json::array();
613 for (uint16_t subVal : *value)
614 {
615 jValue.push_back(subVal);
616 }
James Feistc50e7c62020-07-27 15:39:36 -0700617 }
618 else if (property.first == "MemoryAttributes")
619 {
620 const uint8_t* value =
621 std::get_if<uint8_t>(&property.second);
622
623 if (value == nullptr)
624 {
625 messages::internalError(aResp->res);
626 BMCWEB_LOG_DEBUG
627 << "Invalid property type for MemoryAttributes";
Chicago Duan601af5e2021-04-15 16:59:25 +0800628 return;
James Feistc50e7c62020-07-27 15:39:36 -0700629 }
630 aResp->res.jsonValue["RankCount"] =
631 static_cast<uint64_t>(*value);
632 }
633 else if (property.first == "MemoryConfiguredSpeedInMhz")
634 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700635 const uint16_t* value =
636 std::get_if<uint16_t>(&property.second);
637 if (value == nullptr)
638 {
639 continue;
640 }
641 aResp->res.jsonValue["OperatingSpeedMhz"] = *value;
James Feistc50e7c62020-07-27 15:39:36 -0700642 }
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200643 else if (property.first == "MemoryType")
644 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500645 const auto* value =
Ed Tanousabf2add2019-01-22 16:40:12 -0800646 std::get_if<std::string>(&property.second);
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200647 if (value != nullptr)
648 {
Gunnar Mills313efb12020-10-26 16:05:08 -0500649 std::string memoryDeviceType =
650 translateMemoryTypeToRedfish(*value);
651 // Values like "Unknown" or "Other" will return empty
652 // so just leave off
653 if (!memoryDeviceType.empty())
James Feistc50e7c62020-07-27 15:39:36 -0700654 {
Gunnar Mills313efb12020-10-26 16:05:08 -0500655 aResp->res.jsonValue["MemoryDeviceType"] =
656 memoryDeviceType;
James Feistc50e7c62020-07-27 15:39:36 -0700657 }
James Feistc50e7c62020-07-27 15:39:36 -0700658 if (value->find("DDR") != std::string::npos)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200659 {
660 aResp->res.jsonValue["MemoryType"] = "DRAM";
661 }
James Feistc50e7c62020-07-27 15:39:36 -0700662 else if (boost::ends_with(*value, "Logical"))
663 {
664 aResp->res.jsonValue["MemoryType"] = "IntelOptane";
665 }
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200666 }
667 }
James Feistc50e7c62020-07-27 15:39:36 -0700668 // memory location interface
669 else if (property.first == "Channel" ||
670 property.first == "MemoryController" ||
671 property.first == "Slot" || property.first == "Socket")
672 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700673 const std::string* value =
674 std::get_if<std::string>(&property.second);
675 if (value == nullptr)
676 {
677 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +0800678 return;
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700679 }
James Feistc50e7c62020-07-27 15:39:36 -0700680 aResp->res.jsonValue["MemoryLocation"][property.first] =
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700681 *value;
James Feistc50e7c62020-07-27 15:39:36 -0700682 }
SunnySrivastava1984ee135e22020-12-15 12:42:19 -0600683 else if (property.first == "SparePartNumber")
684 {
685 const std::string* value =
686 std::get_if<std::string>(&property.second);
687 if (value == nullptr)
688 {
689 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +0800690 return;
SunnySrivastava1984ee135e22020-12-15 12:42:19 -0600691 }
692 aResp->res.jsonValue["SparePartNumber"] = *value;
693 }
694 else if (property.first == "Model")
695 {
696 const std::string* value =
697 std::get_if<std::string>(&property.second);
698 if (value == nullptr)
699 {
700 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +0800701 return;
SunnySrivastava1984ee135e22020-12-15 12:42:19 -0600702 }
703 aResp->res.jsonValue["Model"] = *value;
704 }
705 else if (property.first == "LocationCode")
706 {
707 const std::string* value =
708 std::get_if<std::string>(&property.second);
709 if (value == nullptr)
710 {
711 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +0800712 return;
SunnySrivastava1984ee135e22020-12-15 12:42:19 -0600713 }
714 aResp->res
715 .jsonValue["Location"]["PartLocation"]["ServiceLabel"] =
716 *value;
717 }
James Feistc50e7c62020-07-27 15:39:36 -0700718 else
719 {
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800720 getPersistentMemoryProperties(aResp, property);
James Feistc50e7c62020-07-27 15:39:36 -0700721 }
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200722 }
723 },
724 service, objPath, "org.freedesktop.DBus.Properties", "GetAll", "");
725}
726
zhanghch058d1b46d2021-04-01 11:18:24 +0800727inline void getDimmPartitionData(std::shared_ptr<bmcweb::AsyncResp> aResp,
Ed Tanous23a21a12020-07-25 04:45:05 +0000728 const std::string& service,
729 const std::string& path)
James Feist45094ad2020-04-29 14:02:30 -0700730{
731 crow::connections::systemBus->async_method_call(
732 [aResp{std::move(aResp)}](
733 const boost::system::error_code ec,
734 const boost::container::flat_map<
Ed Tanous168e20c2021-12-13 14:39:53 -0800735 std::string, dbus::utility::DbusVariantType>& properties) {
James Feist45094ad2020-04-29 14:02:30 -0700736 if (ec)
737 {
738 BMCWEB_LOG_DEBUG << "DBUS response error";
739 messages::internalError(aResp->res);
740
741 return;
742 }
743
744 nlohmann::json& partition =
745 aResp->res.jsonValue["Regions"].emplace_back(
746 nlohmann::json::object());
747 for (const auto& [key, val] : properties)
748 {
749 if (key == "MemoryClassification")
750 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700751 const std::string* value = std::get_if<std::string>(&val);
752 if (value == nullptr)
753 {
754 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +0800755 return;
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700756 }
757 partition[key] = *value;
James Feist45094ad2020-04-29 14:02:30 -0700758 }
759 else if (key == "OffsetInKiB")
760 {
761 const uint64_t* value = std::get_if<uint64_t>(&val);
762 if (value == nullptr)
763 {
764 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +0800765 return;
James Feist45094ad2020-04-29 14:02:30 -0700766 }
767
768 partition["OffsetMiB"] = (*value >> 10);
769 }
770 else if (key == "PartitionId")
771 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700772 const std::string* value = std::get_if<std::string>(&val);
773 if (value == nullptr)
774 {
775 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +0800776 return;
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700777 }
778 partition["RegionId"] = *value;
James Feist45094ad2020-04-29 14:02:30 -0700779 }
780
781 else if (key == "PassphraseState")
782 {
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700783 const bool* value = std::get_if<bool>(&val);
784 if (value == nullptr)
785 {
786 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +0800787 return;
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700788 }
789 partition["PassphraseEnabled"] = *value;
James Feist45094ad2020-04-29 14:02:30 -0700790 }
791 else if (key == "SizeInKiB")
792 {
793 const uint64_t* value = std::get_if<uint64_t>(&val);
794 if (value == nullptr)
795 {
796 messages::internalError(aResp->res);
797 BMCWEB_LOG_DEBUG
798 << "Invalid property type for SizeInKiB";
Chicago Duan601af5e2021-04-15 16:59:25 +0800799 return;
James Feist45094ad2020-04-29 14:02:30 -0700800 }
801 partition["SizeMiB"] = (*value >> 10);
802 }
803 }
804 },
805
806 service, path, "org.freedesktop.DBus.Properties", "GetAll",
807 "xyz.openbmc_project.Inventory.Item.PersistentMemory.Partition");
808}
809
zhanghch058d1b46d2021-04-01 11:18:24 +0800810inline void getDimmData(std::shared_ptr<bmcweb::AsyncResp> aResp,
Ed Tanous23a21a12020-07-25 04:45:05 +0000811 const std::string& dimmId)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200812{
813 BMCWEB_LOG_DEBUG << "Get available system dimm resources.";
814 crow::connections::systemBus->async_method_call(
Ed Tanous029573d2019-02-01 10:57:49 -0800815 [dimmId, aResp{std::move(aResp)}](
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200816 const boost::system::error_code ec,
817 const boost::container::flat_map<
818 std::string, boost::container::flat_map<
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500819 std::string, std::vector<std::string>>>&
820 subtree) {
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200821 if (ec)
822 {
823 BMCWEB_LOG_DEBUG << "DBUS response error";
824 messages::internalError(aResp->res);
825
826 return;
827 }
James Feist45094ad2020-04-29 14:02:30 -0700828 bool found = false;
829 for (const auto& [path, object] : subtree)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200830 {
James Feist45094ad2020-04-29 14:02:30 -0700831 if (path.find(dimmId) != std::string::npos)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200832 {
James Feist45094ad2020-04-29 14:02:30 -0700833 for (const auto& [service, interfaces] : object)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200834 {
James Feist45094ad2020-04-29 14:02:30 -0700835 if (!found &&
836 (std::find(
837 interfaces.begin(), interfaces.end(),
838 "xyz.openbmc_project.Inventory.Item.Dimm") !=
839 interfaces.end()))
840 {
841 getDimmDataByService(aResp, dimmId, service, path);
842 found = true;
843 }
844
845 // partitions are separate as there can be multiple per
846 // device, i.e.
847 // /xyz/openbmc_project/Inventory/Item/Dimm1/Partition1
848 // /xyz/openbmc_project/Inventory/Item/Dimm1/Partition2
George Liu0fda0f12021-11-16 10:06:17 +0800849 if (std::find(
850 interfaces.begin(), interfaces.end(),
851 "xyz.openbmc_project.Inventory.Item.PersistentMemory.Partition") !=
James Feist45094ad2020-04-29 14:02:30 -0700852 interfaces.end())
853 {
854 getDimmPartitionData(aResp, service, path);
855 }
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200856 }
857 }
858 }
859 // Object not found
James Feist45094ad2020-04-29 14:02:30 -0700860 if (!found)
861 {
862 messages::resourceNotFound(aResp->res, "Memory", dimmId);
863 }
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200864 return;
865 },
866 "xyz.openbmc_project.ObjectMapper",
867 "/xyz/openbmc_project/object_mapper",
868 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
Ed Tanous271584a2019-07-09 16:24:22 -0700869 "/xyz/openbmc_project/inventory", 0,
James Feist45094ad2020-04-29 14:02:30 -0700870 std::array<const char*, 2>{
871 "xyz.openbmc_project.Inventory.Item.Dimm",
872 "xyz.openbmc_project.Inventory.Item.PersistentMemory.Partition"});
Ed Tanous271584a2019-07-09 16:24:22 -0700873}
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200874
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700875inline void requestRoutesMemoryCollection(App& app)
Ed Tanous029573d2019-02-01 10:57:49 -0800876{
Ed Tanous029573d2019-02-01 10:57:49 -0800877 /**
878 * Functions triggers appropriate requests on DBus
879 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700880 BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/Memory/")
Ed Tanoused398212021-06-09 17:05:54 -0700881 .privileges(redfish::privileges::getMemoryCollection)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700882 .methods(boost::beast::http::verb::get)(
883 [](const crow::Request&,
884 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
885 asyncResp->res.jsonValue["@odata.type"] =
886 "#MemoryCollection.MemoryCollection";
887 asyncResp->res.jsonValue["Name"] = "Memory Module Collection";
888 asyncResp->res.jsonValue["@odata.id"] =
889 "/redfish/v1/Systems/system/Memory";
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200890
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700891 collection_util::getCollectionMembers(
892 asyncResp, "/redfish/v1/Systems/system/Memory",
893 {"xyz.openbmc_project.Inventory.Item.Dimm"});
894 });
895}
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200896
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700897inline void requestRoutesMemory(App& app)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200898{
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200899 /**
900 * Functions triggers appropriate requests on DBus
901 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700902 BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/Memory/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -0700903 .privileges(redfish::privileges::getMemory)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700904 .methods(boost::beast::http::verb::get)(
905 [](const crow::Request&,
906 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
907 const std::string& dimmId) {
908 asyncResp->res.jsonValue["@odata.type"] =
909 "#Memory.v1_11_0.Memory";
910 asyncResp->res.jsonValue["@odata.id"] =
911 "/redfish/v1/Systems/system/Memory/" + dimmId;
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200912
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700913 getDimmData(asyncResp, dimmId);
914 });
915}
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200916
917} // namespace redfish