blob: f8af707cd158ffca1d577e1b0d672d01efa25559 [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>
Nan Zhoud7f04fd2022-05-01 01:11:07 +000022#include <nlohmann/json.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>
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +020025#include <sdbusplus/asio/property.hpp>
26#include <sdbusplus/unpack_properties.hpp>
Gunnar Mills116bcc52020-10-14 15:23:42 -050027#include <utils/collection.hpp>
Ed Tanousf201ffb2021-10-09 14:49:28 -070028#include <utils/hex_utils.hpp>
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +020029#include <utils/json_utils.hpp>
30
31namespace redfish
32{
33
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 }
Tyson Tuckerbearce34d512022-09-13 16:26:15 -0700122 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.HBM3")
123 {
124 return "HBM3";
125 }
Gunnar Mills313efb12020-10-26 16:05:08 -0500126 // This is values like Other or Unknown
127 // Also D-Bus values:
128 // DRAM
129 // EDRAM
130 // VRAM
131 // SRAM
132 // RAM
133 // FLASH
134 // EEPROM
135 // FEPROM
136 // EPROM
137 // CDRAM
138 // ThreeDRAM
139 // RDRAM
140 // FBD2
141 // LPDDR_SDRAM
142 // LPDDR2_SDRAM
Mansi Joshi11a2f0f2021-07-19 14:33:27 +0530143 // LPDDR5_SDRAM
Gunnar Mills313efb12020-10-26 16:05:08 -0500144 return "";
145}
146
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200147inline void dimmPropToHex(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
148 const char* key, const uint16_t* value,
149 const nlohmann::json::json_pointer& jsonPtr)
James Feistc50e7c62020-07-27 15:39:36 -0700150{
James Feistc50e7c62020-07-27 15:39:36 -0700151 if (value == nullptr)
152 {
James Feistc50e7c62020-07-27 15:39:36 -0700153 return;
154 }
Nan Zhoud7f04fd2022-05-01 01:11:07 +0000155 aResp->res.jsonValue[jsonPtr][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,
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200160 const dbus::utility::DBusPropertiesMap& properties,
Nan Zhoud7f04fd2022-05-01 01:11:07 +0000161 const nlohmann::json::json_pointer& jsonPtr)
James Feistc50e7c62020-07-27 15:39:36 -0700162{
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200163 const uint16_t* moduleManufacturerID = nullptr;
164 const uint16_t* moduleProductID = nullptr;
165 const uint16_t* subsystemVendorID = nullptr;
166 const uint16_t* subsystemDeviceID = nullptr;
167 const uint64_t* volatileRegionSizeLimitInKiB = nullptr;
168 const uint64_t* pmRegionSizeLimitInKiB = nullptr;
169 const uint64_t* volatileSizeInKiB = nullptr;
170 const uint64_t* pmSizeInKiB = nullptr;
171 const uint64_t* cacheSizeInKB = nullptr;
172 const uint64_t* voltaileRegionMaxSizeInKib = nullptr;
173 const uint64_t* pmRegionMaxSizeInKiB = nullptr;
174 const uint64_t* allocationIncrementInKiB = nullptr;
175 const uint64_t* allocationAlignmentInKiB = nullptr;
176 const uint64_t* volatileRegionNumberLimit = nullptr;
177 const uint64_t* pmRegionNumberLimit = nullptr;
178 const uint64_t* spareDeviceCount = nullptr;
179 const bool* isSpareDeviceInUse = nullptr;
180 const bool* isRankSpareEnabled = nullptr;
181 const std::vector<uint32_t>* maxAveragePowerLimitmW = nullptr;
182 const bool* configurationLocked = nullptr;
183 const std::string* allowedMemoryModes = nullptr;
184 const std::string* memoryMedia = nullptr;
185 const bool* configurationLockCapable = nullptr;
186 const bool* dataLockCapable = nullptr;
187 const bool* passphraseCapable = nullptr;
188 const uint64_t* maxPassphraseCount = nullptr;
189 const uint64_t* passphraseLockLimit = nullptr;
James Feistc50e7c62020-07-27 15:39:36 -0700190
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200191 const bool success = sdbusplus::unpackPropertiesNoThrow(
192 dbus_utils::UnpackErrorPrinter(), properties, "ModuleManufacturerID",
193 moduleManufacturerID, "ModuleProductID", moduleProductID,
194 "SubsystemVendorID", subsystemVendorID, "SubsystemDeviceID",
195 subsystemDeviceID, "VolatileRegionSizeLimitInKiB",
196 volatileRegionSizeLimitInKiB, "PmRegionSizeLimitInKiB",
197 pmRegionSizeLimitInKiB, "VolatileSizeInKiB", volatileSizeInKiB,
198 "PmSizeInKiB", pmSizeInKiB, "CacheSizeInKB", cacheSizeInKB,
199 "VoltaileRegionMaxSizeInKib", voltaileRegionMaxSizeInKib,
200 "PmRegionMaxSizeInKiB", pmRegionMaxSizeInKiB,
201 "AllocationIncrementInKiB", allocationIncrementInKiB,
202 "AllocationAlignmentInKiB", allocationAlignmentInKiB,
203 "VolatileRegionNumberLimit", volatileRegionNumberLimit,
204 "PmRegionNumberLimit", pmRegionNumberLimit, "SpareDeviceCount",
205 spareDeviceCount, "IsSpareDeviceInUse", isSpareDeviceInUse,
206 "IsRankSpareEnabled", isRankSpareEnabled, "MaxAveragePowerLimitmW",
207 maxAveragePowerLimitmW, "ConfigurationLocked", configurationLocked,
208 "AllowedMemoryModes", allowedMemoryModes, "MemoryMedia", memoryMedia,
209 "ConfigurationLockCapable", configurationLockCapable, "DataLockCapable",
210 dataLockCapable, "PassphraseCapable", passphraseCapable,
211 "MaxPassphraseCount", maxPassphraseCount, "PassphraseLockLimit",
212 passphraseLockLimit);
213
214 if (!success)
215 {
216 messages::internalError(aResp->res);
217 return;
218 }
219
220 dimmPropToHex(aResp, "ModuleManufacturerID", moduleManufacturerID, jsonPtr);
221 dimmPropToHex(aResp, "ModuleProductID", moduleProductID, jsonPtr);
222 dimmPropToHex(aResp, "MemorySubsystemControllerManufacturerID",
223 subsystemVendorID, jsonPtr);
224 dimmPropToHex(aResp, "MemorySubsystemControllerProductID",
225 subsystemDeviceID, jsonPtr);
226
227 if (volatileRegionSizeLimitInKiB != nullptr)
228 {
Nan Zhoud7f04fd2022-05-01 01:11:07 +0000229 aResp->res.jsonValue[jsonPtr]["VolatileRegionSizeLimitMiB"] =
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200230 (*volatileRegionSizeLimitInKiB) >> 10;
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800231 }
James Feistc50e7c62020-07-27 15:39:36 -0700232
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200233 if (pmRegionSizeLimitInKiB != nullptr)
234 {
Nan Zhoud7f04fd2022-05-01 01:11:07 +0000235 aResp->res.jsonValue[jsonPtr]["PersistentRegionSizeLimitMiB"] =
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200236 (*pmRegionSizeLimitInKiB) >> 10;
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800237 }
James Feistc50e7c62020-07-27 15:39:36 -0700238
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200239 if (volatileSizeInKiB != nullptr)
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800240 {
James Feistc50e7c62020-07-27 15:39:36 -0700241
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200242 aResp->res.jsonValue[jsonPtr]["VolatileSizeMiB"] =
243 (*volatileSizeInKiB) >> 10;
244 }
245
246 if (pmSizeInKiB != nullptr)
247 {
248 aResp->res.jsonValue[jsonPtr]["NonVolatileSizeMiB"] =
249 (*pmSizeInKiB) >> 10;
250 }
251
252 if (cacheSizeInKB != nullptr)
253 {
254 aResp->res.jsonValue[jsonPtr]["CacheSizeMiB"] = (*cacheSizeInKB >> 10);
255 }
256
257 if (voltaileRegionMaxSizeInKib != nullptr)
258 {
Nan Zhoud7f04fd2022-05-01 01:11:07 +0000259 aResp->res.jsonValue[jsonPtr]["VolatileRegionSizeMaxMiB"] =
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200260 (*voltaileRegionMaxSizeInKib) >> 10;
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800261 }
James Feistc50e7c62020-07-27 15:39:36 -0700262
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200263 if (pmRegionMaxSizeInKiB != nullptr)
264 {
Nan Zhoud7f04fd2022-05-01 01:11:07 +0000265 aResp->res.jsonValue[jsonPtr]["PersistentRegionSizeMaxMiB"] =
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200266 (*pmRegionMaxSizeInKiB) >> 10;
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800267 }
James Feistc50e7c62020-07-27 15:39:36 -0700268
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200269 if (allocationIncrementInKiB != nullptr)
270 {
Nan Zhoud7f04fd2022-05-01 01:11:07 +0000271 aResp->res.jsonValue[jsonPtr]["AllocationIncrementMiB"] =
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200272 (*allocationIncrementInKiB) >> 10;
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800273 }
James Feistc50e7c62020-07-27 15:39:36 -0700274
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200275 if (allocationAlignmentInKiB != nullptr)
276 {
Nan Zhoud7f04fd2022-05-01 01:11:07 +0000277 aResp->res.jsonValue[jsonPtr]["AllocationAlignmentMiB"] =
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200278 (*allocationAlignmentInKiB) >> 10;
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800279 }
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200280
281 if (volatileRegionNumberLimit != nullptr)
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800282 {
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200283 aResp->res.jsonValue[jsonPtr]["VolatileRegionNumberLimit"] =
284 *volatileRegionNumberLimit;
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800285 }
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200286
287 if (pmRegionNumberLimit != nullptr)
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800288 {
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200289 aResp->res.jsonValue[jsonPtr]["PersistentRegionNumberLimit"] =
290 *pmRegionNumberLimit;
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800291 }
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200292
293 if (spareDeviceCount != nullptr)
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800294 {
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200295 aResp->res.jsonValue[jsonPtr]["SpareDeviceCount"] = *spareDeviceCount;
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800296 }
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200297
298 if (isSpareDeviceInUse != nullptr)
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800299 {
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200300 aResp->res.jsonValue[jsonPtr]["IsSpareDeviceEnabled"] =
301 *isSpareDeviceInUse;
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800302 }
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200303
304 if (isRankSpareEnabled != nullptr)
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800305 {
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200306 aResp->res.jsonValue[jsonPtr]["IsRankSpareEnabled"] =
307 *isRankSpareEnabled;
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800308 }
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200309
310 if (maxAveragePowerLimitmW != nullptr)
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800311 {
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200312 aResp->res.jsonValue[jsonPtr]["MaxTDPMilliWatts"] =
313 *maxAveragePowerLimitmW;
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800314 }
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200315
316 if (configurationLocked != nullptr)
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800317 {
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200318 aResp->res.jsonValue[jsonPtr]["ConfigurationLocked"] =
319 *configurationLocked;
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800320 }
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200321
322 if (allowedMemoryModes != nullptr)
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800323 {
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800324 constexpr const std::array<const char*, 3> values{"Volatile", "PMEM",
325 "Block"};
James Feistc50e7c62020-07-27 15:39:36 -0700326
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800327 for (const char* v : values)
328 {
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200329 if (allowedMemoryModes->ends_with(v))
James Feistc50e7c62020-07-27 15:39:36 -0700330 {
Nan Zhoud7f04fd2022-05-01 01:11:07 +0000331 aResp->res.jsonValue[jsonPtr]["OperatingMemoryModes"].push_back(
332 v);
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800333 break;
James Feistc50e7c62020-07-27 15:39:36 -0700334 }
335 }
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800336 }
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200337
338 if (memoryMedia != nullptr)
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800339 {
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800340 constexpr const std::array<const char*, 3> values{"DRAM", "NAND",
341 "Intel3DXPoint"};
James Feistc50e7c62020-07-27 15:39:36 -0700342
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800343 for (const char* v : values)
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700344 {
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200345 if (memoryMedia->ends_with(v))
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700346 {
Nan Zhoud7f04fd2022-05-01 01:11:07 +0000347 aResp->res.jsonValue[jsonPtr]["MemoryMedia"].push_back(v);
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800348 break;
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700349 }
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700350 }
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800351 }
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200352
353 if (configurationLockCapable != nullptr)
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800354 {
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200355 aResp->res.jsonValue[jsonPtr]["SecurityCapabilities"]
356 ["ConfigurationLockCapable"] =
357 *configurationLockCapable;
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800358 }
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200359
360 if (dataLockCapable != nullptr)
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800361 {
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200362 aResp->res
363 .jsonValue[jsonPtr]["SecurityCapabilities"]["DataLockCapable"] =
364 *dataLockCapable;
365 }
366
367 if (passphraseCapable != nullptr)
368 {
369 aResp->res
370 .jsonValue[jsonPtr]["SecurityCapabilities"]["PassphraseCapable"] =
371 *passphraseCapable;
372 }
373
374 if (maxPassphraseCount != nullptr)
375 {
376 aResp->res
377 .jsonValue[jsonPtr]["SecurityCapabilities"]["MaxPassphraseCount"] =
378 *maxPassphraseCount;
379 }
380
381 if (passphraseLockLimit != nullptr)
382 {
383 aResp->res
384 .jsonValue[jsonPtr]["SecurityCapabilities"]["PassphraseLockLimit"] =
385 *passphraseLockLimit;
James Feistc50e7c62020-07-27 15:39:36 -0700386 }
387}
388
Nan Zhou9a5acea2022-05-17 21:12:43 +0000389inline void
390 assembleDimmProperties(std::string_view dimmId,
391 const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Nan Zhoud7f04fd2022-05-01 01:11:07 +0000392 const dbus::utility::DBusPropertiesMap& properties,
393 const nlohmann::json::json_pointer& jsonPtr)
Nan Zhou9a5acea2022-05-17 21:12:43 +0000394{
Nan Zhoud7f04fd2022-05-01 01:11:07 +0000395 aResp->res.jsonValue[jsonPtr]["Id"] = dimmId;
396 aResp->res.jsonValue[jsonPtr]["Name"] = "DIMM Slot";
397 aResp->res.jsonValue[jsonPtr]["Status"]["State"] = "Enabled";
398 aResp->res.jsonValue[jsonPtr]["Status"]["Health"] = "OK";
Nan Zhou9a5acea2022-05-17 21:12:43 +0000399
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200400 const uint16_t* memoryDataWidth = nullptr;
401 const size_t* memorySizeInKB = nullptr;
402 const std::string* partNumber = nullptr;
403 const std::string* serialNumber = nullptr;
404 const std::string* manufacturer = nullptr;
405 const uint16_t* revisionCode = nullptr;
406 const bool* present = nullptr;
407 const uint16_t* memoryTotalWidth = nullptr;
408 const std::string* ecc = nullptr;
409 const std::string* formFactor = nullptr;
410 const std::vector<uint16_t>* allowedSpeedsMT = nullptr;
411 const uint8_t* memoryAttributes = nullptr;
412 const uint16_t* memoryConfiguredSpeedInMhz = nullptr;
413 const std::string* memoryType = nullptr;
414 const std::string* channel = nullptr;
415 const std::string* memoryController = nullptr;
416 const std::string* slot = nullptr;
417 const std::string* socket = nullptr;
418 const std::string* sparePartNumber = nullptr;
419 const std::string* model = nullptr;
420 const std::string* locationCode = nullptr;
421
422 const bool success = sdbusplus::unpackPropertiesNoThrow(
423 dbus_utils::UnpackErrorPrinter(), properties, "MemoryDataWidth",
424 memoryDataWidth, "MemorySizeInKB", memorySizeInKB, "PartNumber",
Nikhil Namjoshi656472d2022-09-13 20:54:44 +0000425 partNumber, "SerialNumber", serialNumber, "Manufacturer", manufacturer,
426 "RevisionCode", revisionCode, "Present", present, "MemoryTotalWidth",
427 memoryTotalWidth, "ECC", ecc, "FormFactor", formFactor,
428 "AllowedSpeedsMT", allowedSpeedsMT, "MemoryAttributes",
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200429 memoryAttributes, "MemoryConfiguredSpeedInMhz",
430 memoryConfiguredSpeedInMhz, "MemoryType", memoryType, "Channel",
431 channel, "MemoryController", memoryController, "Slot", slot, "Socket",
432 socket, "SparePartNumber", sparePartNumber, "Model", model,
433 "LocationCode", locationCode);
434
435 if (!success)
Nan Zhou9a5acea2022-05-17 21:12:43 +0000436 {
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200437 messages::internalError(aResp->res);
438 return;
439 }
Nan Zhou9a5acea2022-05-17 21:12:43 +0000440
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200441 if (memoryDataWidth != nullptr)
442 {
443 aResp->res.jsonValue[jsonPtr]["DataWidthBits"] = *memoryDataWidth;
444 }
Nan Zhou9a5acea2022-05-17 21:12:43 +0000445
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200446 if (memorySizeInKB != nullptr)
447 {
448 aResp->res.jsonValue[jsonPtr]["CapacityMiB"] = (*memorySizeInKB >> 10);
449 }
Nan Zhou9a5acea2022-05-17 21:12:43 +0000450
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200451 if (partNumber != nullptr)
452 {
453 aResp->res.jsonValue[jsonPtr]["PartNumber"] = *partNumber;
454 }
Nan Zhou9a5acea2022-05-17 21:12:43 +0000455
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200456 if (serialNumber != nullptr)
457 {
458 aResp->res.jsonValue[jsonPtr]["SerialNumber"] = *serialNumber;
459 }
460
461 if (manufacturer != nullptr)
462 {
463 aResp->res.jsonValue[jsonPtr]["Manufacturer"] = *manufacturer;
464 }
465
466 if (revisionCode != nullptr)
467 {
468 aResp->res.jsonValue[jsonPtr]["FirmwareRevision"] =
469 std::to_string(*revisionCode);
470 }
471
472 if (present != nullptr && !*present)
473 {
474 aResp->res.jsonValue[jsonPtr]["Status"]["State"] = "Absent";
475 }
476
477 if (memoryTotalWidth != nullptr)
478 {
479 aResp->res.jsonValue[jsonPtr]["BusWidthBits"] = *memoryTotalWidth;
480 }
481
482 if (ecc != nullptr)
483 {
484 constexpr const std::array<const char*, 4> values{
485 "NoECC", "SingleBitECC", "MultiBitECC", "AddressParity"};
486
487 for (const char* v : values)
Nan Zhou9a5acea2022-05-17 21:12:43 +0000488 {
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200489 if (ecc->ends_with(v))
Nan Zhou9a5acea2022-05-17 21:12:43 +0000490 {
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200491 aResp->res.jsonValue[jsonPtr]["ErrorCorrection"] = v;
492 break;
Nan Zhou9a5acea2022-05-17 21:12:43 +0000493 }
Nan Zhou9a5acea2022-05-17 21:12:43 +0000494 }
495 }
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200496
497 if (formFactor != nullptr)
498 {
499 constexpr const std::array<const char*, 11> values{
500 "RDIMM", "UDIMM", "SO_DIMM", "LRDIMM",
501 "Mini_RDIMM", "Mini_UDIMM", "SO_RDIMM_72b", "SO_UDIMM_72b",
502 "SO_DIMM_16b", "SO_DIMM_32b", "Die"};
503
504 for (const char* v : values)
505 {
506 if (formFactor->ends_with(v))
507 {
508 aResp->res.jsonValue[jsonPtr]["BaseModuleType"] = v;
509 break;
510 }
511 }
512 }
513
514 if (allowedSpeedsMT != nullptr)
515 {
516 nlohmann::json& jValue =
517 aResp->res.jsonValue[jsonPtr]["AllowedSpeedsMHz"];
518 jValue = nlohmann::json::array();
519 for (uint16_t subVal : *allowedSpeedsMT)
520 {
521 jValue.push_back(subVal);
522 }
523 }
524
525 if (memoryAttributes != nullptr)
526 {
527 aResp->res.jsonValue[jsonPtr]["RankCount"] =
528 static_cast<uint64_t>(*memoryAttributes);
529 }
530
531 if (memoryConfiguredSpeedInMhz != nullptr)
532 {
533 aResp->res.jsonValue[jsonPtr]["OperatingSpeedMhz"] =
534 *memoryConfiguredSpeedInMhz;
535 }
536
537 if (memoryType != nullptr)
538 {
539 std::string memoryDeviceType =
540 translateMemoryTypeToRedfish(*memoryType);
541 // Values like "Unknown" or "Other" will return empty
542 // so just leave off
543 if (!memoryDeviceType.empty())
544 {
545 aResp->res.jsonValue[jsonPtr]["MemoryDeviceType"] =
546 memoryDeviceType;
547 }
548 if (memoryType->find("DDR") != std::string::npos)
549 {
550 aResp->res.jsonValue[jsonPtr]["MemoryType"] = "DRAM";
551 }
552 else if (memoryType->ends_with("Logical"))
553 {
554 aResp->res.jsonValue[jsonPtr]["MemoryType"] = "IntelOptane";
555 }
556 }
557
558 if (channel != nullptr)
559 {
560 aResp->res.jsonValue[jsonPtr]["MemoryLocation"]["Channel"] = *channel;
561 }
562
563 if (memoryController != nullptr)
564 {
565 aResp->res.jsonValue[jsonPtr]["MemoryLocation"]["MemoryController"] =
566 *memoryController;
567 }
568
569 if (slot != nullptr)
570 {
571 aResp->res.jsonValue[jsonPtr]["MemoryLocation"]["Slot"] = *slot;
572 }
573
574 if (socket != nullptr)
575 {
576 aResp->res.jsonValue[jsonPtr]["MemoryLocation"]["Socket"] = *socket;
577 }
578
579 if (sparePartNumber != nullptr)
580 {
581 aResp->res.jsonValue[jsonPtr]["SparePartNumber"] = *sparePartNumber;
582 }
583
584 if (model != nullptr)
585 {
586 aResp->res.jsonValue[jsonPtr]["Model"] = *model;
587 }
588
589 if (locationCode != nullptr)
590 {
591 aResp->res
592 .jsonValue[jsonPtr]["Location"]["PartLocation"]["ServiceLabel"] =
593 *locationCode;
594 }
595
596 getPersistentMemoryProperties(aResp, properties, jsonPtr);
Nan Zhou9a5acea2022-05-17 21:12:43 +0000597}
598
zhanghch058d1b46d2021-04-01 11:18:24 +0800599inline void getDimmDataByService(std::shared_ptr<bmcweb::AsyncResp> aResp,
Ed Tanous80789c82020-08-19 09:19:09 -0700600 const std::string& dimmId,
601 const std::string& service,
602 const std::string& objPath)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200603{
James Feist35e257a2020-06-05 13:30:51 -0700604 auto health = std::make_shared<HealthPopulate>(aResp);
605 health->selfPath = objPath;
606 health->populate();
607
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200608 BMCWEB_LOG_DEBUG << "Get available system components.";
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200609 sdbusplus::asio::getAllProperties(
610 *crow::connections::systemBus, service, objPath, "",
Ed Tanousb9d36b42022-02-26 21:42:46 -0800611 [dimmId, aResp{std::move(aResp)}](
612 const boost::system::error_code ec,
613 const dbus::utility::DBusPropertiesMap& properties) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700614 if (ec)
615 {
616 BMCWEB_LOG_DEBUG << "DBUS response error";
617 messages::internalError(aResp->res);
618 return;
619 }
Nan Zhoud7f04fd2022-05-01 01:11:07 +0000620 assembleDimmProperties(dimmId, aResp, properties, ""_json_pointer);
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200621 });
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200622}
623
Nan Zhouef00d7d2022-05-20 21:22:32 +0000624inline void assembleDimmPartitionData(
625 const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Nan Zhoud7f04fd2022-05-01 01:11:07 +0000626 const dbus::utility::DBusPropertiesMap& properties,
627 const nlohmann::json::json_pointer& regionPtr)
Nan Zhouef00d7d2022-05-20 21:22:32 +0000628{
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200629 const std::string* memoryClassification = nullptr;
630 const uint64_t* offsetInKiB = nullptr;
631 const std::string* partitionId = nullptr;
632 const bool* passphraseState = nullptr;
633 const uint64_t* sizeInKiB = nullptr;
634
635 const bool success = sdbusplus::unpackPropertiesNoThrow(
636 dbus_utils::UnpackErrorPrinter(), properties, "MemoryClassification",
637 memoryClassification, "OffsetInKiB", offsetInKiB, "PartitionId",
638 partitionId, "PassphraseState", passphraseState, "SizeInKiB",
639 sizeInKiB);
640
641 if (!success)
Nan Zhouef00d7d2022-05-20 21:22:32 +0000642 {
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200643 messages::internalError(aResp->res);
644 return;
Nan Zhouef00d7d2022-05-20 21:22:32 +0000645 }
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200646
647 nlohmann::json::object_t partition;
648
649 if (memoryClassification != nullptr)
650 {
651 partition["MemoryClassification"] = *memoryClassification;
652 }
653
654 if (offsetInKiB != nullptr)
655 {
656 partition["OffsetMiB"] = (*offsetInKiB >> 10);
657 }
658
659 if (partitionId != nullptr)
660 {
661 partition["RegionId"] = *partitionId;
662 }
663
664 if (passphraseState != nullptr)
665 {
666 partition["PassphraseEnabled"] = *passphraseState;
667 }
668
669 if (sizeInKiB != nullptr)
670 {
671 partition["SizeMiB"] = (*sizeInKiB >> 10);
672 }
673
Nan Zhoud7f04fd2022-05-01 01:11:07 +0000674 aResp->res.jsonValue[regionPtr].emplace_back(std::move(partition));
Nan Zhouef00d7d2022-05-20 21:22:32 +0000675}
676
zhanghch058d1b46d2021-04-01 11:18:24 +0800677inline void getDimmPartitionData(std::shared_ptr<bmcweb::AsyncResp> aResp,
Ed Tanous23a21a12020-07-25 04:45:05 +0000678 const std::string& service,
679 const std::string& path)
James Feist45094ad2020-04-29 14:02:30 -0700680{
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200681 sdbusplus::asio::getAllProperties(
682 *crow::connections::systemBus, service, path,
683 "xyz.openbmc_project.Inventory.Item.PersistentMemory.Partition",
James Feist45094ad2020-04-29 14:02:30 -0700684 [aResp{std::move(aResp)}](
685 const boost::system::error_code ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -0800686 const dbus::utility::DBusPropertiesMap& properties) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700687 if (ec)
688 {
689 BMCWEB_LOG_DEBUG << "DBUS response error";
690 messages::internalError(aResp->res);
James Feist45094ad2020-04-29 14:02:30 -0700691
Ed Tanous002d39b2022-05-31 08:59:27 -0700692 return;
693 }
Nan Zhoud7f04fd2022-05-01 01:11:07 +0000694 nlohmann::json::json_pointer regionPtr = "/Regions"_json_pointer;
695 assembleDimmPartitionData(aResp, properties, regionPtr);
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200696 }
James Feist45094ad2020-04-29 14:02:30 -0700697
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200698 );
James Feist45094ad2020-04-29 14:02:30 -0700699}
700
zhanghch058d1b46d2021-04-01 11:18:24 +0800701inline void getDimmData(std::shared_ptr<bmcweb::AsyncResp> aResp,
Ed Tanous23a21a12020-07-25 04:45:05 +0000702 const std::string& dimmId)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200703{
704 BMCWEB_LOG_DEBUG << "Get available system dimm resources.";
705 crow::connections::systemBus->async_method_call(
Ed Tanous029573d2019-02-01 10:57:49 -0800706 [dimmId, aResp{std::move(aResp)}](
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200707 const boost::system::error_code ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -0800708 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700709 if (ec)
710 {
711 BMCWEB_LOG_DEBUG << "DBUS response error";
712 messages::internalError(aResp->res);
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200713
Ed Tanous002d39b2022-05-31 08:59:27 -0700714 return;
715 }
716 bool found = false;
Nan Zhou76686dc2022-06-17 23:01:51 +0000717 for (const auto& [rawPath, object] : subtree)
Ed Tanous002d39b2022-05-31 08:59:27 -0700718 {
Nan Zhou76686dc2022-06-17 23:01:51 +0000719 sdbusplus::message::object_path path(rawPath);
720 for (const auto& [service, interfaces] : object)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200721 {
Nan Zhou76686dc2022-06-17 23:01:51 +0000722 for (const auto& interface : interfaces)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200723 {
Nan Zhou76686dc2022-06-17 23:01:51 +0000724 if (interface ==
725 "xyz.openbmc_project.Inventory.Item.Dimm" &&
726 path.filename() == dimmId)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200727 {
Nan Zhou76686dc2022-06-17 23:01:51 +0000728 getDimmDataByService(aResp, dimmId, service, rawPath);
729 found = true;
730 }
James Feist45094ad2020-04-29 14:02:30 -0700731
Nan Zhou76686dc2022-06-17 23:01:51 +0000732 // partitions are separate as there can be multiple
733 // per
734 // device, i.e.
735 // /xyz/openbmc_project/Inventory/Item/Dimm1/Partition1
736 // /xyz/openbmc_project/Inventory/Item/Dimm1/Partition2
737 if (interface ==
738 "xyz.openbmc_project.Inventory.Item.PersistentMemory.Partition" &&
739 path.parent_path().filename() == dimmId)
740 {
741 getDimmPartitionData(aResp, service, rawPath);
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200742 }
743 }
744 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700745 }
746 // Object not found
747 if (!found)
748 {
749 messages::resourceNotFound(aResp->res, "Memory", dimmId);
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200750 return;
Ed Tanous002d39b2022-05-31 08:59:27 -0700751 }
752 // Set @odata only if object is found
753 aResp->res.jsonValue["@odata.type"] = "#Memory.v1_11_0.Memory";
754 aResp->res.jsonValue["@odata.id"] =
755 "/redfish/v1/Systems/system/Memory/" + dimmId;
756 return;
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200757 },
758 "xyz.openbmc_project.ObjectMapper",
759 "/xyz/openbmc_project/object_mapper",
760 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
Ed Tanous271584a2019-07-09 16:24:22 -0700761 "/xyz/openbmc_project/inventory", 0,
James Feist45094ad2020-04-29 14:02:30 -0700762 std::array<const char*, 2>{
763 "xyz.openbmc_project.Inventory.Item.Dimm",
764 "xyz.openbmc_project.Inventory.Item.PersistentMemory.Partition"});
Ed Tanous271584a2019-07-09 16:24:22 -0700765}
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200766
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700767inline void requestRoutesMemoryCollection(App& app)
Ed Tanous029573d2019-02-01 10:57:49 -0800768{
Ed Tanous029573d2019-02-01 10:57:49 -0800769 /**
770 * Functions triggers appropriate requests on DBus
771 */
Ed Tanous22d268c2022-05-19 09:39:07 -0700772 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Memory/")
Ed Tanoused398212021-06-09 17:05:54 -0700773 .privileges(redfish::privileges::getMemoryCollection)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700774 .methods(boost::beast::http::verb::get)(
Ed Tanous45ca1b82022-03-25 13:07:27 -0700775 [&app](const crow::Request& req,
Ed Tanous22d268c2022-05-19 09:39:07 -0700776 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
777 const std::string& systemName) {
Carson Labrado3ba00072022-06-06 19:40:56 +0000778 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -0700779 {
780 return;
781 }
Ed Tanous22d268c2022-05-19 09:39:07 -0700782 if (systemName != "system")
783 {
784 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
785 systemName);
786 return;
787 }
788
Ed Tanous002d39b2022-05-31 08:59:27 -0700789 asyncResp->res.jsonValue["@odata.type"] =
790 "#MemoryCollection.MemoryCollection";
791 asyncResp->res.jsonValue["Name"] = "Memory Module Collection";
792 asyncResp->res.jsonValue["@odata.id"] =
793 "/redfish/v1/Systems/system/Memory";
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200794
Ed Tanous002d39b2022-05-31 08:59:27 -0700795 collection_util::getCollectionMembers(
Willy Tuae9031f2022-09-27 05:48:07 +0000796 asyncResp, boost::urls::url("/redfish/v1/Systems/system/Memory"),
Ed Tanous002d39b2022-05-31 08:59:27 -0700797 {"xyz.openbmc_project.Inventory.Item.Dimm"});
798 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700799}
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200800
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700801inline void requestRoutesMemory(App& app)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200802{
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200803 /**
804 * Functions triggers appropriate requests on DBus
805 */
Ed Tanous22d268c2022-05-19 09:39:07 -0700806 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Memory/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -0700807 .privileges(redfish::privileges::getMemory)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700808 .methods(boost::beast::http::verb::get)(
Ed Tanous45ca1b82022-03-25 13:07:27 -0700809 [&app](const crow::Request& req,
810 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous22d268c2022-05-19 09:39:07 -0700811 const std::string& systemName, const std::string& dimmId) {
Carson Labrado3ba00072022-06-06 19:40:56 +0000812 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -0700813 {
814 return;
815 }
Ed Tanous22d268c2022-05-19 09:39:07 -0700816 if (systemName != "system")
817 {
818 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
819 systemName);
820 return;
821 }
822
Ed Tanous002d39b2022-05-31 08:59:27 -0700823 getDimmData(asyncResp, dimmId);
824 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700825}
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200826
827} // namespace redfish