blob: dcd017dcff3f9586b784a8c9b4ee54997bb9ae21 [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 }
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
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200143inline void dimmPropToHex(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
144 const char* key, const uint16_t* value,
145 const nlohmann::json::json_pointer& jsonPtr)
James Feistc50e7c62020-07-27 15:39:36 -0700146{
James Feistc50e7c62020-07-27 15:39:36 -0700147 if (value == nullptr)
148 {
James Feistc50e7c62020-07-27 15:39:36 -0700149 return;
150 }
Nan Zhoud7f04fd2022-05-01 01:11:07 +0000151 aResp->res.jsonValue[jsonPtr][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,
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200156 const dbus::utility::DBusPropertiesMap& properties,
Nan Zhoud7f04fd2022-05-01 01:11:07 +0000157 const nlohmann::json::json_pointer& jsonPtr)
James Feistc50e7c62020-07-27 15:39:36 -0700158{
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200159 const uint16_t* moduleManufacturerID = nullptr;
160 const uint16_t* moduleProductID = nullptr;
161 const uint16_t* subsystemVendorID = nullptr;
162 const uint16_t* subsystemDeviceID = nullptr;
163 const uint64_t* volatileRegionSizeLimitInKiB = nullptr;
164 const uint64_t* pmRegionSizeLimitInKiB = nullptr;
165 const uint64_t* volatileSizeInKiB = nullptr;
166 const uint64_t* pmSizeInKiB = nullptr;
167 const uint64_t* cacheSizeInKB = nullptr;
168 const uint64_t* voltaileRegionMaxSizeInKib = nullptr;
169 const uint64_t* pmRegionMaxSizeInKiB = nullptr;
170 const uint64_t* allocationIncrementInKiB = nullptr;
171 const uint64_t* allocationAlignmentInKiB = nullptr;
172 const uint64_t* volatileRegionNumberLimit = nullptr;
173 const uint64_t* pmRegionNumberLimit = nullptr;
174 const uint64_t* spareDeviceCount = nullptr;
175 const bool* isSpareDeviceInUse = nullptr;
176 const bool* isRankSpareEnabled = nullptr;
177 const std::vector<uint32_t>* maxAveragePowerLimitmW = nullptr;
178 const bool* configurationLocked = nullptr;
179 const std::string* allowedMemoryModes = nullptr;
180 const std::string* memoryMedia = nullptr;
181 const bool* configurationLockCapable = nullptr;
182 const bool* dataLockCapable = nullptr;
183 const bool* passphraseCapable = nullptr;
184 const uint64_t* maxPassphraseCount = nullptr;
185 const uint64_t* passphraseLockLimit = nullptr;
James Feistc50e7c62020-07-27 15:39:36 -0700186
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200187 const bool success = sdbusplus::unpackPropertiesNoThrow(
188 dbus_utils::UnpackErrorPrinter(), properties, "ModuleManufacturerID",
189 moduleManufacturerID, "ModuleProductID", moduleProductID,
190 "SubsystemVendorID", subsystemVendorID, "SubsystemDeviceID",
191 subsystemDeviceID, "VolatileRegionSizeLimitInKiB",
192 volatileRegionSizeLimitInKiB, "PmRegionSizeLimitInKiB",
193 pmRegionSizeLimitInKiB, "VolatileSizeInKiB", volatileSizeInKiB,
194 "PmSizeInKiB", pmSizeInKiB, "CacheSizeInKB", cacheSizeInKB,
195 "VoltaileRegionMaxSizeInKib", voltaileRegionMaxSizeInKib,
196 "PmRegionMaxSizeInKiB", pmRegionMaxSizeInKiB,
197 "AllocationIncrementInKiB", allocationIncrementInKiB,
198 "AllocationAlignmentInKiB", allocationAlignmentInKiB,
199 "VolatileRegionNumberLimit", volatileRegionNumberLimit,
200 "PmRegionNumberLimit", pmRegionNumberLimit, "SpareDeviceCount",
201 spareDeviceCount, "IsSpareDeviceInUse", isSpareDeviceInUse,
202 "IsRankSpareEnabled", isRankSpareEnabled, "MaxAveragePowerLimitmW",
203 maxAveragePowerLimitmW, "ConfigurationLocked", configurationLocked,
204 "AllowedMemoryModes", allowedMemoryModes, "MemoryMedia", memoryMedia,
205 "ConfigurationLockCapable", configurationLockCapable, "DataLockCapable",
206 dataLockCapable, "PassphraseCapable", passphraseCapable,
207 "MaxPassphraseCount", maxPassphraseCount, "PassphraseLockLimit",
208 passphraseLockLimit);
209
210 if (!success)
211 {
212 messages::internalError(aResp->res);
213 return;
214 }
215
216 dimmPropToHex(aResp, "ModuleManufacturerID", moduleManufacturerID, jsonPtr);
217 dimmPropToHex(aResp, "ModuleProductID", moduleProductID, jsonPtr);
218 dimmPropToHex(aResp, "MemorySubsystemControllerManufacturerID",
219 subsystemVendorID, jsonPtr);
220 dimmPropToHex(aResp, "MemorySubsystemControllerProductID",
221 subsystemDeviceID, jsonPtr);
222
223 if (volatileRegionSizeLimitInKiB != nullptr)
224 {
Nan Zhoud7f04fd2022-05-01 01:11:07 +0000225 aResp->res.jsonValue[jsonPtr]["VolatileRegionSizeLimitMiB"] =
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200226 (*volatileRegionSizeLimitInKiB) >> 10;
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800227 }
James Feistc50e7c62020-07-27 15:39:36 -0700228
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200229 if (pmRegionSizeLimitInKiB != nullptr)
230 {
Nan Zhoud7f04fd2022-05-01 01:11:07 +0000231 aResp->res.jsonValue[jsonPtr]["PersistentRegionSizeLimitMiB"] =
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200232 (*pmRegionSizeLimitInKiB) >> 10;
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800233 }
James Feistc50e7c62020-07-27 15:39:36 -0700234
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200235 if (volatileSizeInKiB != nullptr)
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800236 {
James Feistc50e7c62020-07-27 15:39:36 -0700237
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200238 aResp->res.jsonValue[jsonPtr]["VolatileSizeMiB"] =
239 (*volatileSizeInKiB) >> 10;
240 }
241
242 if (pmSizeInKiB != nullptr)
243 {
244 aResp->res.jsonValue[jsonPtr]["NonVolatileSizeMiB"] =
245 (*pmSizeInKiB) >> 10;
246 }
247
248 if (cacheSizeInKB != nullptr)
249 {
250 aResp->res.jsonValue[jsonPtr]["CacheSizeMiB"] = (*cacheSizeInKB >> 10);
251 }
252
253 if (voltaileRegionMaxSizeInKib != nullptr)
254 {
Nan Zhoud7f04fd2022-05-01 01:11:07 +0000255 aResp->res.jsonValue[jsonPtr]["VolatileRegionSizeMaxMiB"] =
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200256 (*voltaileRegionMaxSizeInKib) >> 10;
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800257 }
James Feistc50e7c62020-07-27 15:39:36 -0700258
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200259 if (pmRegionMaxSizeInKiB != nullptr)
260 {
Nan Zhoud7f04fd2022-05-01 01:11:07 +0000261 aResp->res.jsonValue[jsonPtr]["PersistentRegionSizeMaxMiB"] =
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200262 (*pmRegionMaxSizeInKiB) >> 10;
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800263 }
James Feistc50e7c62020-07-27 15:39:36 -0700264
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200265 if (allocationIncrementInKiB != nullptr)
266 {
Nan Zhoud7f04fd2022-05-01 01:11:07 +0000267 aResp->res.jsonValue[jsonPtr]["AllocationIncrementMiB"] =
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200268 (*allocationIncrementInKiB) >> 10;
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800269 }
James Feistc50e7c62020-07-27 15:39:36 -0700270
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200271 if (allocationAlignmentInKiB != nullptr)
272 {
Nan Zhoud7f04fd2022-05-01 01:11:07 +0000273 aResp->res.jsonValue[jsonPtr]["AllocationAlignmentMiB"] =
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200274 (*allocationAlignmentInKiB) >> 10;
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800275 }
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200276
277 if (volatileRegionNumberLimit != nullptr)
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800278 {
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200279 aResp->res.jsonValue[jsonPtr]["VolatileRegionNumberLimit"] =
280 *volatileRegionNumberLimit;
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800281 }
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200282
283 if (pmRegionNumberLimit != nullptr)
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800284 {
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200285 aResp->res.jsonValue[jsonPtr]["PersistentRegionNumberLimit"] =
286 *pmRegionNumberLimit;
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800287 }
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200288
289 if (spareDeviceCount != nullptr)
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800290 {
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200291 aResp->res.jsonValue[jsonPtr]["SpareDeviceCount"] = *spareDeviceCount;
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800292 }
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200293
294 if (isSpareDeviceInUse != nullptr)
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800295 {
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200296 aResp->res.jsonValue[jsonPtr]["IsSpareDeviceEnabled"] =
297 *isSpareDeviceInUse;
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800298 }
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200299
300 if (isRankSpareEnabled != nullptr)
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800301 {
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200302 aResp->res.jsonValue[jsonPtr]["IsRankSpareEnabled"] =
303 *isRankSpareEnabled;
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800304 }
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200305
306 if (maxAveragePowerLimitmW != nullptr)
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800307 {
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200308 aResp->res.jsonValue[jsonPtr]["MaxTDPMilliWatts"] =
309 *maxAveragePowerLimitmW;
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800310 }
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200311
312 if (configurationLocked != nullptr)
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800313 {
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200314 aResp->res.jsonValue[jsonPtr]["ConfigurationLocked"] =
315 *configurationLocked;
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800316 }
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200317
318 if (allowedMemoryModes != nullptr)
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800319 {
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800320 constexpr const std::array<const char*, 3> values{"Volatile", "PMEM",
321 "Block"};
James Feistc50e7c62020-07-27 15:39:36 -0700322
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800323 for (const char* v : values)
324 {
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200325 if (allowedMemoryModes->ends_with(v))
James Feistc50e7c62020-07-27 15:39:36 -0700326 {
Nan Zhoud7f04fd2022-05-01 01:11:07 +0000327 aResp->res.jsonValue[jsonPtr]["OperatingMemoryModes"].push_back(
328 v);
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800329 break;
James Feistc50e7c62020-07-27 15:39:36 -0700330 }
331 }
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800332 }
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200333
334 if (memoryMedia != nullptr)
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800335 {
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800336 constexpr const std::array<const char*, 3> values{"DRAM", "NAND",
337 "Intel3DXPoint"};
James Feistc50e7c62020-07-27 15:39:36 -0700338
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800339 for (const char* v : values)
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700340 {
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200341 if (memoryMedia->ends_with(v))
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700342 {
Nan Zhoud7f04fd2022-05-01 01:11:07 +0000343 aResp->res.jsonValue[jsonPtr]["MemoryMedia"].push_back(v);
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800344 break;
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700345 }
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700346 }
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800347 }
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200348
349 if (configurationLockCapable != nullptr)
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800350 {
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200351 aResp->res.jsonValue[jsonPtr]["SecurityCapabilities"]
352 ["ConfigurationLockCapable"] =
353 *configurationLockCapable;
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800354 }
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200355
356 if (dataLockCapable != nullptr)
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800357 {
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200358 aResp->res
359 .jsonValue[jsonPtr]["SecurityCapabilities"]["DataLockCapable"] =
360 *dataLockCapable;
361 }
362
363 if (passphraseCapable != nullptr)
364 {
365 aResp->res
366 .jsonValue[jsonPtr]["SecurityCapabilities"]["PassphraseCapable"] =
367 *passphraseCapable;
368 }
369
370 if (maxPassphraseCount != nullptr)
371 {
372 aResp->res
373 .jsonValue[jsonPtr]["SecurityCapabilities"]["MaxPassphraseCount"] =
374 *maxPassphraseCount;
375 }
376
377 if (passphraseLockLimit != nullptr)
378 {
379 aResp->res
380 .jsonValue[jsonPtr]["SecurityCapabilities"]["PassphraseLockLimit"] =
381 *passphraseLockLimit;
James Feistc50e7c62020-07-27 15:39:36 -0700382 }
383}
384
Nan Zhou9a5acea2022-05-17 21:12:43 +0000385inline void
386 assembleDimmProperties(std::string_view dimmId,
387 const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Nan Zhoud7f04fd2022-05-01 01:11:07 +0000388 const dbus::utility::DBusPropertiesMap& properties,
389 const nlohmann::json::json_pointer& jsonPtr)
Nan Zhou9a5acea2022-05-17 21:12:43 +0000390{
Nan Zhoud7f04fd2022-05-01 01:11:07 +0000391 aResp->res.jsonValue[jsonPtr]["Id"] = dimmId;
392 aResp->res.jsonValue[jsonPtr]["Name"] = "DIMM Slot";
393 aResp->res.jsonValue[jsonPtr]["Status"]["State"] = "Enabled";
394 aResp->res.jsonValue[jsonPtr]["Status"]["Health"] = "OK";
Nan Zhou9a5acea2022-05-17 21:12:43 +0000395
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200396 const uint16_t* memoryDataWidth = nullptr;
397 const size_t* memorySizeInKB = nullptr;
398 const std::string* partNumber = nullptr;
399 const std::string* serialNumber = nullptr;
400 const std::string* manufacturer = nullptr;
401 const uint16_t* revisionCode = nullptr;
402 const bool* present = nullptr;
403 const uint16_t* memoryTotalWidth = nullptr;
404 const std::string* ecc = nullptr;
405 const std::string* formFactor = nullptr;
406 const std::vector<uint16_t>* allowedSpeedsMT = nullptr;
407 const uint8_t* memoryAttributes = nullptr;
408 const uint16_t* memoryConfiguredSpeedInMhz = nullptr;
409 const std::string* memoryType = nullptr;
410 const std::string* channel = nullptr;
411 const std::string* memoryController = nullptr;
412 const std::string* slot = nullptr;
413 const std::string* socket = nullptr;
414 const std::string* sparePartNumber = nullptr;
415 const std::string* model = nullptr;
416 const std::string* locationCode = nullptr;
417
418 const bool success = sdbusplus::unpackPropertiesNoThrow(
419 dbus_utils::UnpackErrorPrinter(), properties, "MemoryDataWidth",
420 memoryDataWidth, "MemorySizeInKB", memorySizeInKB, "PartNumber",
421 partNumber, "SerialNumber", serialNumber, "Present", present,
422 "MemoryTotalWidth", memoryTotalWidth, "ECC", ecc, "FormFactor",
423 formFactor, "AllowedSpeedsMT", allowedSpeedsMT, "MemoryAttributes",
424 memoryAttributes, "MemoryConfiguredSpeedInMhz",
425 memoryConfiguredSpeedInMhz, "MemoryType", memoryType, "Channel",
426 channel, "MemoryController", memoryController, "Slot", slot, "Socket",
427 socket, "SparePartNumber", sparePartNumber, "Model", model,
428 "LocationCode", locationCode);
429
430 if (!success)
Nan Zhou9a5acea2022-05-17 21:12:43 +0000431 {
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200432 messages::internalError(aResp->res);
433 return;
434 }
Nan Zhou9a5acea2022-05-17 21:12:43 +0000435
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200436 if (memoryDataWidth != nullptr)
437 {
438 aResp->res.jsonValue[jsonPtr]["DataWidthBits"] = *memoryDataWidth;
439 }
Nan Zhou9a5acea2022-05-17 21:12:43 +0000440
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200441 if (memorySizeInKB != nullptr)
442 {
443 aResp->res.jsonValue[jsonPtr]["CapacityMiB"] = (*memorySizeInKB >> 10);
444 }
Nan Zhou9a5acea2022-05-17 21:12:43 +0000445
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200446 if (partNumber != nullptr)
447 {
448 aResp->res.jsonValue[jsonPtr]["PartNumber"] = *partNumber;
449 }
Nan Zhou9a5acea2022-05-17 21:12:43 +0000450
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200451 if (serialNumber != nullptr)
452 {
453 aResp->res.jsonValue[jsonPtr]["SerialNumber"] = *serialNumber;
454 }
455
456 if (manufacturer != nullptr)
457 {
458 aResp->res.jsonValue[jsonPtr]["Manufacturer"] = *manufacturer;
459 }
460
461 if (revisionCode != nullptr)
462 {
463 aResp->res.jsonValue[jsonPtr]["FirmwareRevision"] =
464 std::to_string(*revisionCode);
465 }
466
467 if (present != nullptr && !*present)
468 {
469 aResp->res.jsonValue[jsonPtr]["Status"]["State"] = "Absent";
470 }
471
472 if (memoryTotalWidth != nullptr)
473 {
474 aResp->res.jsonValue[jsonPtr]["BusWidthBits"] = *memoryTotalWidth;
475 }
476
477 if (ecc != nullptr)
478 {
479 constexpr const std::array<const char*, 4> values{
480 "NoECC", "SingleBitECC", "MultiBitECC", "AddressParity"};
481
482 for (const char* v : values)
Nan Zhou9a5acea2022-05-17 21:12:43 +0000483 {
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200484 if (ecc->ends_with(v))
Nan Zhou9a5acea2022-05-17 21:12:43 +0000485 {
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200486 aResp->res.jsonValue[jsonPtr]["ErrorCorrection"] = v;
487 break;
Nan Zhou9a5acea2022-05-17 21:12:43 +0000488 }
Nan Zhou9a5acea2022-05-17 21:12:43 +0000489 }
490 }
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200491
492 if (formFactor != nullptr)
493 {
494 constexpr const std::array<const char*, 11> values{
495 "RDIMM", "UDIMM", "SO_DIMM", "LRDIMM",
496 "Mini_RDIMM", "Mini_UDIMM", "SO_RDIMM_72b", "SO_UDIMM_72b",
497 "SO_DIMM_16b", "SO_DIMM_32b", "Die"};
498
499 for (const char* v : values)
500 {
501 if (formFactor->ends_with(v))
502 {
503 aResp->res.jsonValue[jsonPtr]["BaseModuleType"] = v;
504 break;
505 }
506 }
507 }
508
509 if (allowedSpeedsMT != nullptr)
510 {
511 nlohmann::json& jValue =
512 aResp->res.jsonValue[jsonPtr]["AllowedSpeedsMHz"];
513 jValue = nlohmann::json::array();
514 for (uint16_t subVal : *allowedSpeedsMT)
515 {
516 jValue.push_back(subVal);
517 }
518 }
519
520 if (memoryAttributes != nullptr)
521 {
522 aResp->res.jsonValue[jsonPtr]["RankCount"] =
523 static_cast<uint64_t>(*memoryAttributes);
524 }
525
526 if (memoryConfiguredSpeedInMhz != nullptr)
527 {
528 aResp->res.jsonValue[jsonPtr]["OperatingSpeedMhz"] =
529 *memoryConfiguredSpeedInMhz;
530 }
531
532 if (memoryType != nullptr)
533 {
534 std::string memoryDeviceType =
535 translateMemoryTypeToRedfish(*memoryType);
536 // Values like "Unknown" or "Other" will return empty
537 // so just leave off
538 if (!memoryDeviceType.empty())
539 {
540 aResp->res.jsonValue[jsonPtr]["MemoryDeviceType"] =
541 memoryDeviceType;
542 }
543 if (memoryType->find("DDR") != std::string::npos)
544 {
545 aResp->res.jsonValue[jsonPtr]["MemoryType"] = "DRAM";
546 }
547 else if (memoryType->ends_with("Logical"))
548 {
549 aResp->res.jsonValue[jsonPtr]["MemoryType"] = "IntelOptane";
550 }
551 }
552
553 if (channel != nullptr)
554 {
555 aResp->res.jsonValue[jsonPtr]["MemoryLocation"]["Channel"] = *channel;
556 }
557
558 if (memoryController != nullptr)
559 {
560 aResp->res.jsonValue[jsonPtr]["MemoryLocation"]["MemoryController"] =
561 *memoryController;
562 }
563
564 if (slot != nullptr)
565 {
566 aResp->res.jsonValue[jsonPtr]["MemoryLocation"]["Slot"] = *slot;
567 }
568
569 if (socket != nullptr)
570 {
571 aResp->res.jsonValue[jsonPtr]["MemoryLocation"]["Socket"] = *socket;
572 }
573
574 if (sparePartNumber != nullptr)
575 {
576 aResp->res.jsonValue[jsonPtr]["SparePartNumber"] = *sparePartNumber;
577 }
578
579 if (model != nullptr)
580 {
581 aResp->res.jsonValue[jsonPtr]["Model"] = *model;
582 }
583
584 if (locationCode != nullptr)
585 {
586 aResp->res
587 .jsonValue[jsonPtr]["Location"]["PartLocation"]["ServiceLabel"] =
588 *locationCode;
589 }
590
591 getPersistentMemoryProperties(aResp, properties, jsonPtr);
Nan Zhou9a5acea2022-05-17 21:12:43 +0000592}
593
zhanghch058d1b46d2021-04-01 11:18:24 +0800594inline void getDimmDataByService(std::shared_ptr<bmcweb::AsyncResp> aResp,
Ed Tanous80789c82020-08-19 09:19:09 -0700595 const std::string& dimmId,
596 const std::string& service,
597 const std::string& objPath)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200598{
James Feist35e257a2020-06-05 13:30:51 -0700599 auto health = std::make_shared<HealthPopulate>(aResp);
600 health->selfPath = objPath;
601 health->populate();
602
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200603 BMCWEB_LOG_DEBUG << "Get available system components.";
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200604 sdbusplus::asio::getAllProperties(
605 *crow::connections::systemBus, service, objPath, "",
Ed Tanousb9d36b42022-02-26 21:42:46 -0800606 [dimmId, aResp{std::move(aResp)}](
607 const boost::system::error_code ec,
608 const dbus::utility::DBusPropertiesMap& properties) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700609 if (ec)
610 {
611 BMCWEB_LOG_DEBUG << "DBUS response error";
612 messages::internalError(aResp->res);
613 return;
614 }
Nan Zhoud7f04fd2022-05-01 01:11:07 +0000615 assembleDimmProperties(dimmId, aResp, properties, ""_json_pointer);
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200616 });
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200617}
618
Nan Zhouef00d7d2022-05-20 21:22:32 +0000619inline void assembleDimmPartitionData(
620 const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Nan Zhoud7f04fd2022-05-01 01:11:07 +0000621 const dbus::utility::DBusPropertiesMap& properties,
622 const nlohmann::json::json_pointer& regionPtr)
Nan Zhouef00d7d2022-05-20 21:22:32 +0000623{
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200624 const std::string* memoryClassification = nullptr;
625 const uint64_t* offsetInKiB = nullptr;
626 const std::string* partitionId = nullptr;
627 const bool* passphraseState = nullptr;
628 const uint64_t* sizeInKiB = nullptr;
629
630 const bool success = sdbusplus::unpackPropertiesNoThrow(
631 dbus_utils::UnpackErrorPrinter(), properties, "MemoryClassification",
632 memoryClassification, "OffsetInKiB", offsetInKiB, "PartitionId",
633 partitionId, "PassphraseState", passphraseState, "SizeInKiB",
634 sizeInKiB);
635
636 if (!success)
Nan Zhouef00d7d2022-05-20 21:22:32 +0000637 {
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200638 messages::internalError(aResp->res);
639 return;
Nan Zhouef00d7d2022-05-20 21:22:32 +0000640 }
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200641
642 nlohmann::json::object_t partition;
643
644 if (memoryClassification != nullptr)
645 {
646 partition["MemoryClassification"] = *memoryClassification;
647 }
648
649 if (offsetInKiB != nullptr)
650 {
651 partition["OffsetMiB"] = (*offsetInKiB >> 10);
652 }
653
654 if (partitionId != nullptr)
655 {
656 partition["RegionId"] = *partitionId;
657 }
658
659 if (passphraseState != nullptr)
660 {
661 partition["PassphraseEnabled"] = *passphraseState;
662 }
663
664 if (sizeInKiB != nullptr)
665 {
666 partition["SizeMiB"] = (*sizeInKiB >> 10);
667 }
668
Nan Zhoud7f04fd2022-05-01 01:11:07 +0000669 aResp->res.jsonValue[regionPtr].emplace_back(std::move(partition));
Nan Zhouef00d7d2022-05-20 21:22:32 +0000670}
671
zhanghch058d1b46d2021-04-01 11:18:24 +0800672inline void getDimmPartitionData(std::shared_ptr<bmcweb::AsyncResp> aResp,
Ed Tanous23a21a12020-07-25 04:45:05 +0000673 const std::string& service,
674 const std::string& path)
James Feist45094ad2020-04-29 14:02:30 -0700675{
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200676 sdbusplus::asio::getAllProperties(
677 *crow::connections::systemBus, service, path,
678 "xyz.openbmc_project.Inventory.Item.PersistentMemory.Partition",
James Feist45094ad2020-04-29 14:02:30 -0700679 [aResp{std::move(aResp)}](
680 const boost::system::error_code ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -0800681 const dbus::utility::DBusPropertiesMap& properties) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700682 if (ec)
683 {
684 BMCWEB_LOG_DEBUG << "DBUS response error";
685 messages::internalError(aResp->res);
James Feist45094ad2020-04-29 14:02:30 -0700686
Ed Tanous002d39b2022-05-31 08:59:27 -0700687 return;
688 }
Nan Zhoud7f04fd2022-05-01 01:11:07 +0000689 nlohmann::json::json_pointer regionPtr = "/Regions"_json_pointer;
690 assembleDimmPartitionData(aResp, properties, regionPtr);
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200691 }
James Feist45094ad2020-04-29 14:02:30 -0700692
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200693 );
James Feist45094ad2020-04-29 14:02:30 -0700694}
695
zhanghch058d1b46d2021-04-01 11:18:24 +0800696inline void getDimmData(std::shared_ptr<bmcweb::AsyncResp> aResp,
Ed Tanous23a21a12020-07-25 04:45:05 +0000697 const std::string& dimmId)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200698{
699 BMCWEB_LOG_DEBUG << "Get available system dimm resources.";
700 crow::connections::systemBus->async_method_call(
Ed Tanous029573d2019-02-01 10:57:49 -0800701 [dimmId, aResp{std::move(aResp)}](
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200702 const boost::system::error_code ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -0800703 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700704 if (ec)
705 {
706 BMCWEB_LOG_DEBUG << "DBUS response error";
707 messages::internalError(aResp->res);
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200708
Ed Tanous002d39b2022-05-31 08:59:27 -0700709 return;
710 }
711 bool found = false;
Nan Zhou76686dc2022-06-17 23:01:51 +0000712 for (const auto& [rawPath, object] : subtree)
Ed Tanous002d39b2022-05-31 08:59:27 -0700713 {
Nan Zhou76686dc2022-06-17 23:01:51 +0000714 sdbusplus::message::object_path path(rawPath);
715 for (const auto& [service, interfaces] : object)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200716 {
Nan Zhou76686dc2022-06-17 23:01:51 +0000717 for (const auto& interface : interfaces)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200718 {
Nan Zhou76686dc2022-06-17 23:01:51 +0000719 if (interface ==
720 "xyz.openbmc_project.Inventory.Item.Dimm" &&
721 path.filename() == dimmId)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200722 {
Nan Zhou76686dc2022-06-17 23:01:51 +0000723 getDimmDataByService(aResp, dimmId, service, rawPath);
724 found = true;
725 }
James Feist45094ad2020-04-29 14:02:30 -0700726
Nan Zhou76686dc2022-06-17 23:01:51 +0000727 // partitions are separate as there can be multiple
728 // per
729 // device, i.e.
730 // /xyz/openbmc_project/Inventory/Item/Dimm1/Partition1
731 // /xyz/openbmc_project/Inventory/Item/Dimm1/Partition2
732 if (interface ==
733 "xyz.openbmc_project.Inventory.Item.PersistentMemory.Partition" &&
734 path.parent_path().filename() == dimmId)
735 {
736 getDimmPartitionData(aResp, service, rawPath);
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200737 }
738 }
739 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700740 }
741 // Object not found
742 if (!found)
743 {
744 messages::resourceNotFound(aResp->res, "Memory", dimmId);
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200745 return;
Ed Tanous002d39b2022-05-31 08:59:27 -0700746 }
747 // Set @odata only if object is found
748 aResp->res.jsonValue["@odata.type"] = "#Memory.v1_11_0.Memory";
749 aResp->res.jsonValue["@odata.id"] =
750 "/redfish/v1/Systems/system/Memory/" + dimmId;
751 return;
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200752 },
753 "xyz.openbmc_project.ObjectMapper",
754 "/xyz/openbmc_project/object_mapper",
755 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
Ed Tanous271584a2019-07-09 16:24:22 -0700756 "/xyz/openbmc_project/inventory", 0,
James Feist45094ad2020-04-29 14:02:30 -0700757 std::array<const char*, 2>{
758 "xyz.openbmc_project.Inventory.Item.Dimm",
759 "xyz.openbmc_project.Inventory.Item.PersistentMemory.Partition"});
Ed Tanous271584a2019-07-09 16:24:22 -0700760}
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200761
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700762inline void requestRoutesMemoryCollection(App& app)
Ed Tanous029573d2019-02-01 10:57:49 -0800763{
Ed Tanous029573d2019-02-01 10:57:49 -0800764 /**
765 * Functions triggers appropriate requests on DBus
766 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700767 BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/Memory/")
Ed Tanoused398212021-06-09 17:05:54 -0700768 .privileges(redfish::privileges::getMemoryCollection)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700769 .methods(boost::beast::http::verb::get)(
Ed Tanous45ca1b82022-03-25 13:07:27 -0700770 [&app](const crow::Request& req,
771 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
Carson Labrado3ba00072022-06-06 19:40:56 +0000772 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -0700773 {
774 return;
775 }
776 asyncResp->res.jsonValue["@odata.type"] =
777 "#MemoryCollection.MemoryCollection";
778 asyncResp->res.jsonValue["Name"] = "Memory Module Collection";
779 asyncResp->res.jsonValue["@odata.id"] =
780 "/redfish/v1/Systems/system/Memory";
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200781
Ed Tanous002d39b2022-05-31 08:59:27 -0700782 collection_util::getCollectionMembers(
783 asyncResp, "/redfish/v1/Systems/system/Memory",
784 {"xyz.openbmc_project.Inventory.Item.Dimm"});
785 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700786}
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200787
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700788inline void requestRoutesMemory(App& app)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200789{
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200790 /**
791 * Functions triggers appropriate requests on DBus
792 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700793 BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/Memory/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -0700794 .privileges(redfish::privileges::getMemory)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700795 .methods(boost::beast::http::verb::get)(
Ed Tanous45ca1b82022-03-25 13:07:27 -0700796 [&app](const crow::Request& req,
797 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
798 const std::string& dimmId) {
Carson Labrado3ba00072022-06-06 19:40:56 +0000799 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -0700800 {
801 return;
802 }
803 getDimmData(asyncResp, dimmId);
804 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700805}
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200806
807} // namespace redfish