blob: 3e3360b60822dcc1d2a848211cc42f1c40fc83c4 [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
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080018#include "app.hpp"
19#include "dbus_utility.hpp"
James Feist35e257a2020-06-05 13:30:51 -070020#include "health.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080021#include "query.hpp"
22#include "registries/privilege_registry.hpp"
23#include "utils/collection.hpp"
24#include "utils/dbus_utils.hpp"
25#include "utils/hex_utils.hpp"
26#include "utils/json_utils.hpp"
James Feist35e257a2020-06-05 13:30:51 -070027
Nan Zhoud7f04fd2022-05-01 01:11:07 +000028#include <nlohmann/json.hpp>
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +020029#include <sdbusplus/asio/property.hpp>
30#include <sdbusplus/unpack_properties.hpp>
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +020031
George Liu7a1dbc42022-12-07 16:03:22 +080032#include <array>
33#include <string_view>
34
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +020035namespace redfish
36{
37
Gunnar Mills313efb12020-10-26 16:05:08 -050038inline std::string translateMemoryTypeToRedfish(const std::string& memoryType)
39{
40 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR")
41 {
42 return "DDR";
43 }
44 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR2")
45 {
46 return "DDR2";
47 }
48 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR3")
49 {
50 return "DDR3";
51 }
52 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR4")
53 {
54 return "DDR4";
55 }
56 if (memoryType ==
57 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR4E_SDRAM")
58 {
59 return "DDR4E_SDRAM";
60 }
Mansi Joshi11a2f0f2021-07-19 14:33:27 +053061 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR5")
62 {
63 return "DDR5";
64 }
Gunnar Mills313efb12020-10-26 16:05:08 -050065 if (memoryType ==
66 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.LPDDR4_SDRAM")
67 {
68 return "LPDDR4_SDRAM";
69 }
70 if (memoryType ==
71 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.LPDDR3_SDRAM")
72 {
73 return "LPDDR3_SDRAM";
74 }
75 if (memoryType ==
76 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR2_SDRAM_FB_DIMM")
77 {
78 return "DDR2_SDRAM_FB_DIMM";
79 }
George Liu0fda0f12021-11-16 10:06:17 +080080 if (memoryType ==
81 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR2_SDRAM_FB_DIMM_PROB")
Gunnar Mills313efb12020-10-26 16:05:08 -050082 {
83 return "DDR2_SDRAM_FB_DIMM_PROBE";
84 }
85 if (memoryType ==
86 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR_SGRAM")
87 {
88 return "DDR_SGRAM";
89 }
90 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.ROM")
91 {
92 return "ROM";
93 }
94 if (memoryType ==
95 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.SDRAM")
96 {
97 return "SDRAM";
98 }
99 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.EDO")
100 {
101 return "EDO";
102 }
103 if (memoryType ==
104 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.FastPageMode")
105 {
106 return "FastPageMode";
107 }
108 if (memoryType ==
109 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.PipelinedNibble")
110 {
111 return "PipelinedNibble";
112 }
113 if (memoryType ==
114 "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.Logical")
115 {
116 return "Logical";
117 }
118 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.HBM")
119 {
120 return "HBM";
121 }
122 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.HBM2")
123 {
124 return "HBM2";
125 }
Tyson Tuckerbearce34d512022-09-13 16:26:15 -0700126 if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.HBM3")
127 {
128 return "HBM3";
129 }
Gunnar Mills313efb12020-10-26 16:05:08 -0500130 // This is values like Other or Unknown
131 // Also D-Bus values:
132 // DRAM
133 // EDRAM
134 // VRAM
135 // SRAM
136 // RAM
137 // FLASH
138 // EEPROM
139 // FEPROM
140 // EPROM
141 // CDRAM
142 // ThreeDRAM
143 // RDRAM
144 // FBD2
145 // LPDDR_SDRAM
146 // LPDDR2_SDRAM
Mansi Joshi11a2f0f2021-07-19 14:33:27 +0530147 // LPDDR5_SDRAM
Gunnar Mills313efb12020-10-26 16:05:08 -0500148 return "";
149}
150
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200151inline void dimmPropToHex(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
152 const char* key, const uint16_t* value,
153 const nlohmann::json::json_pointer& jsonPtr)
James Feistc50e7c62020-07-27 15:39:36 -0700154{
James Feistc50e7c62020-07-27 15:39:36 -0700155 if (value == nullptr)
156 {
James Feistc50e7c62020-07-27 15:39:36 -0700157 return;
158 }
Nan Zhoud7f04fd2022-05-01 01:11:07 +0000159 aResp->res.jsonValue[jsonPtr][key] = "0x" + intToHexString(*value, 4);
James Feistc50e7c62020-07-27 15:39:36 -0700160}
161
zhanghch058d1b46d2021-04-01 11:18:24 +0800162inline void getPersistentMemoryProperties(
163 const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200164 const dbus::utility::DBusPropertiesMap& properties,
Nan Zhoud7f04fd2022-05-01 01:11:07 +0000165 const nlohmann::json::json_pointer& jsonPtr)
James Feistc50e7c62020-07-27 15:39:36 -0700166{
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200167 const uint16_t* moduleManufacturerID = nullptr;
168 const uint16_t* moduleProductID = nullptr;
169 const uint16_t* subsystemVendorID = nullptr;
170 const uint16_t* subsystemDeviceID = nullptr;
171 const uint64_t* volatileRegionSizeLimitInKiB = nullptr;
172 const uint64_t* pmRegionSizeLimitInKiB = nullptr;
173 const uint64_t* volatileSizeInKiB = nullptr;
174 const uint64_t* pmSizeInKiB = nullptr;
175 const uint64_t* cacheSizeInKB = nullptr;
176 const uint64_t* voltaileRegionMaxSizeInKib = nullptr;
177 const uint64_t* pmRegionMaxSizeInKiB = nullptr;
178 const uint64_t* allocationIncrementInKiB = nullptr;
179 const uint64_t* allocationAlignmentInKiB = nullptr;
180 const uint64_t* volatileRegionNumberLimit = nullptr;
181 const uint64_t* pmRegionNumberLimit = nullptr;
182 const uint64_t* spareDeviceCount = nullptr;
183 const bool* isSpareDeviceInUse = nullptr;
184 const bool* isRankSpareEnabled = nullptr;
185 const std::vector<uint32_t>* maxAveragePowerLimitmW = nullptr;
186 const bool* configurationLocked = nullptr;
187 const std::string* allowedMemoryModes = nullptr;
188 const std::string* memoryMedia = nullptr;
189 const bool* configurationLockCapable = nullptr;
190 const bool* dataLockCapable = nullptr;
191 const bool* passphraseCapable = nullptr;
192 const uint64_t* maxPassphraseCount = nullptr;
193 const uint64_t* passphraseLockLimit = nullptr;
James Feistc50e7c62020-07-27 15:39:36 -0700194
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200195 const bool success = sdbusplus::unpackPropertiesNoThrow(
196 dbus_utils::UnpackErrorPrinter(), properties, "ModuleManufacturerID",
197 moduleManufacturerID, "ModuleProductID", moduleProductID,
198 "SubsystemVendorID", subsystemVendorID, "SubsystemDeviceID",
199 subsystemDeviceID, "VolatileRegionSizeLimitInKiB",
200 volatileRegionSizeLimitInKiB, "PmRegionSizeLimitInKiB",
201 pmRegionSizeLimitInKiB, "VolatileSizeInKiB", volatileSizeInKiB,
202 "PmSizeInKiB", pmSizeInKiB, "CacheSizeInKB", cacheSizeInKB,
203 "VoltaileRegionMaxSizeInKib", voltaileRegionMaxSizeInKib,
204 "PmRegionMaxSizeInKiB", pmRegionMaxSizeInKiB,
205 "AllocationIncrementInKiB", allocationIncrementInKiB,
206 "AllocationAlignmentInKiB", allocationAlignmentInKiB,
207 "VolatileRegionNumberLimit", volatileRegionNumberLimit,
208 "PmRegionNumberLimit", pmRegionNumberLimit, "SpareDeviceCount",
209 spareDeviceCount, "IsSpareDeviceInUse", isSpareDeviceInUse,
210 "IsRankSpareEnabled", isRankSpareEnabled, "MaxAveragePowerLimitmW",
211 maxAveragePowerLimitmW, "ConfigurationLocked", configurationLocked,
212 "AllowedMemoryModes", allowedMemoryModes, "MemoryMedia", memoryMedia,
213 "ConfigurationLockCapable", configurationLockCapable, "DataLockCapable",
214 dataLockCapable, "PassphraseCapable", passphraseCapable,
215 "MaxPassphraseCount", maxPassphraseCount, "PassphraseLockLimit",
216 passphraseLockLimit);
217
218 if (!success)
219 {
220 messages::internalError(aResp->res);
221 return;
222 }
223
224 dimmPropToHex(aResp, "ModuleManufacturerID", moduleManufacturerID, jsonPtr);
225 dimmPropToHex(aResp, "ModuleProductID", moduleProductID, jsonPtr);
226 dimmPropToHex(aResp, "MemorySubsystemControllerManufacturerID",
227 subsystemVendorID, jsonPtr);
228 dimmPropToHex(aResp, "MemorySubsystemControllerProductID",
229 subsystemDeviceID, jsonPtr);
230
231 if (volatileRegionSizeLimitInKiB != nullptr)
232 {
Nan Zhoud7f04fd2022-05-01 01:11:07 +0000233 aResp->res.jsonValue[jsonPtr]["VolatileRegionSizeLimitMiB"] =
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200234 (*volatileRegionSizeLimitInKiB) >> 10;
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800235 }
James Feistc50e7c62020-07-27 15:39:36 -0700236
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200237 if (pmRegionSizeLimitInKiB != nullptr)
238 {
Nan Zhoud7f04fd2022-05-01 01:11:07 +0000239 aResp->res.jsonValue[jsonPtr]["PersistentRegionSizeLimitMiB"] =
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200240 (*pmRegionSizeLimitInKiB) >> 10;
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800241 }
James Feistc50e7c62020-07-27 15:39:36 -0700242
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200243 if (volatileSizeInKiB != nullptr)
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800244 {
James Feistc50e7c62020-07-27 15:39:36 -0700245
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200246 aResp->res.jsonValue[jsonPtr]["VolatileSizeMiB"] =
247 (*volatileSizeInKiB) >> 10;
248 }
249
250 if (pmSizeInKiB != nullptr)
251 {
252 aResp->res.jsonValue[jsonPtr]["NonVolatileSizeMiB"] =
253 (*pmSizeInKiB) >> 10;
254 }
255
256 if (cacheSizeInKB != nullptr)
257 {
258 aResp->res.jsonValue[jsonPtr]["CacheSizeMiB"] = (*cacheSizeInKB >> 10);
259 }
260
261 if (voltaileRegionMaxSizeInKib != nullptr)
262 {
Nan Zhoud7f04fd2022-05-01 01:11:07 +0000263 aResp->res.jsonValue[jsonPtr]["VolatileRegionSizeMaxMiB"] =
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200264 (*voltaileRegionMaxSizeInKib) >> 10;
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800265 }
James Feistc50e7c62020-07-27 15:39:36 -0700266
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200267 if (pmRegionMaxSizeInKiB != nullptr)
268 {
Nan Zhoud7f04fd2022-05-01 01:11:07 +0000269 aResp->res.jsonValue[jsonPtr]["PersistentRegionSizeMaxMiB"] =
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200270 (*pmRegionMaxSizeInKiB) >> 10;
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800271 }
James Feistc50e7c62020-07-27 15:39:36 -0700272
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200273 if (allocationIncrementInKiB != nullptr)
274 {
Nan Zhoud7f04fd2022-05-01 01:11:07 +0000275 aResp->res.jsonValue[jsonPtr]["AllocationIncrementMiB"] =
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200276 (*allocationIncrementInKiB) >> 10;
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800277 }
James Feistc50e7c62020-07-27 15:39:36 -0700278
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200279 if (allocationAlignmentInKiB != nullptr)
280 {
Nan Zhoud7f04fd2022-05-01 01:11:07 +0000281 aResp->res.jsonValue[jsonPtr]["AllocationAlignmentMiB"] =
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200282 (*allocationAlignmentInKiB) >> 10;
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800283 }
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200284
285 if (volatileRegionNumberLimit != nullptr)
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800286 {
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200287 aResp->res.jsonValue[jsonPtr]["VolatileRegionNumberLimit"] =
288 *volatileRegionNumberLimit;
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800289 }
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200290
291 if (pmRegionNumberLimit != nullptr)
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800292 {
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200293 aResp->res.jsonValue[jsonPtr]["PersistentRegionNumberLimit"] =
294 *pmRegionNumberLimit;
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800295 }
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200296
297 if (spareDeviceCount != nullptr)
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800298 {
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200299 aResp->res.jsonValue[jsonPtr]["SpareDeviceCount"] = *spareDeviceCount;
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800300 }
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200301
302 if (isSpareDeviceInUse != nullptr)
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800303 {
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200304 aResp->res.jsonValue[jsonPtr]["IsSpareDeviceEnabled"] =
305 *isSpareDeviceInUse;
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800306 }
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200307
308 if (isRankSpareEnabled != nullptr)
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800309 {
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200310 aResp->res.jsonValue[jsonPtr]["IsRankSpareEnabled"] =
311 *isRankSpareEnabled;
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800312 }
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200313
314 if (maxAveragePowerLimitmW != nullptr)
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800315 {
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200316 aResp->res.jsonValue[jsonPtr]["MaxTDPMilliWatts"] =
317 *maxAveragePowerLimitmW;
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800318 }
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200319
320 if (configurationLocked != nullptr)
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800321 {
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200322 aResp->res.jsonValue[jsonPtr]["ConfigurationLocked"] =
323 *configurationLocked;
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800324 }
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200325
326 if (allowedMemoryModes != nullptr)
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800327 {
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800328 constexpr const std::array<const char*, 3> values{"Volatile", "PMEM",
329 "Block"};
James Feistc50e7c62020-07-27 15:39:36 -0700330
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800331 for (const char* v : values)
332 {
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200333 if (allowedMemoryModes->ends_with(v))
James Feistc50e7c62020-07-27 15:39:36 -0700334 {
Nan Zhoud7f04fd2022-05-01 01:11:07 +0000335 aResp->res.jsonValue[jsonPtr]["OperatingMemoryModes"].push_back(
336 v);
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800337 break;
James Feistc50e7c62020-07-27 15:39:36 -0700338 }
339 }
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800340 }
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200341
342 if (memoryMedia != nullptr)
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800343 {
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800344 constexpr const std::array<const char*, 3> values{"DRAM", "NAND",
345 "Intel3DXPoint"};
James Feistc50e7c62020-07-27 15:39:36 -0700346
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800347 for (const char* v : values)
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700348 {
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200349 if (memoryMedia->ends_with(v))
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700350 {
Nan Zhoud7f04fd2022-05-01 01:11:07 +0000351 aResp->res.jsonValue[jsonPtr]["MemoryMedia"].push_back(v);
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800352 break;
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700353 }
Ed Tanous5fb91ba2020-09-28 15:41:28 -0700354 }
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800355 }
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200356
357 if (configurationLockCapable != nullptr)
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800358 {
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200359 aResp->res.jsonValue[jsonPtr]["SecurityCapabilities"]
360 ["ConfigurationLockCapable"] =
361 *configurationLockCapable;
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800362 }
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200363
364 if (dataLockCapable != nullptr)
Jiaqing Zhao80badf72022-03-18 17:48:53 +0800365 {
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200366 aResp->res
367 .jsonValue[jsonPtr]["SecurityCapabilities"]["DataLockCapable"] =
368 *dataLockCapable;
369 }
370
371 if (passphraseCapable != nullptr)
372 {
373 aResp->res
374 .jsonValue[jsonPtr]["SecurityCapabilities"]["PassphraseCapable"] =
375 *passphraseCapable;
376 }
377
378 if (maxPassphraseCount != nullptr)
379 {
380 aResp->res
381 .jsonValue[jsonPtr]["SecurityCapabilities"]["MaxPassphraseCount"] =
382 *maxPassphraseCount;
383 }
384
385 if (passphraseLockLimit != nullptr)
386 {
387 aResp->res
388 .jsonValue[jsonPtr]["SecurityCapabilities"]["PassphraseLockLimit"] =
389 *passphraseLockLimit;
James Feistc50e7c62020-07-27 15:39:36 -0700390 }
391}
392
Nan Zhou9a5acea2022-05-17 21:12:43 +0000393inline void
394 assembleDimmProperties(std::string_view dimmId,
395 const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Nan Zhoud7f04fd2022-05-01 01:11:07 +0000396 const dbus::utility::DBusPropertiesMap& properties,
397 const nlohmann::json::json_pointer& jsonPtr)
Nan Zhou9a5acea2022-05-17 21:12:43 +0000398{
Nan Zhoud7f04fd2022-05-01 01:11:07 +0000399 aResp->res.jsonValue[jsonPtr]["Id"] = dimmId;
400 aResp->res.jsonValue[jsonPtr]["Name"] = "DIMM Slot";
401 aResp->res.jsonValue[jsonPtr]["Status"]["State"] = "Enabled";
402 aResp->res.jsonValue[jsonPtr]["Status"]["Health"] = "OK";
Nan Zhou9a5acea2022-05-17 21:12:43 +0000403
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200404 const uint16_t* memoryDataWidth = nullptr;
405 const size_t* memorySizeInKB = nullptr;
406 const std::string* partNumber = nullptr;
407 const std::string* serialNumber = nullptr;
408 const std::string* manufacturer = nullptr;
409 const uint16_t* revisionCode = nullptr;
410 const bool* present = nullptr;
411 const uint16_t* memoryTotalWidth = nullptr;
412 const std::string* ecc = nullptr;
413 const std::string* formFactor = nullptr;
414 const std::vector<uint16_t>* allowedSpeedsMT = nullptr;
415 const uint8_t* memoryAttributes = nullptr;
416 const uint16_t* memoryConfiguredSpeedInMhz = nullptr;
417 const std::string* memoryType = nullptr;
418 const std::string* channel = nullptr;
419 const std::string* memoryController = nullptr;
420 const std::string* slot = nullptr;
421 const std::string* socket = nullptr;
422 const std::string* sparePartNumber = nullptr;
423 const std::string* model = nullptr;
424 const std::string* locationCode = nullptr;
425
426 const bool success = sdbusplus::unpackPropertiesNoThrow(
427 dbus_utils::UnpackErrorPrinter(), properties, "MemoryDataWidth",
428 memoryDataWidth, "MemorySizeInKB", memorySizeInKB, "PartNumber",
Nikhil Namjoshi656472d2022-09-13 20:54:44 +0000429 partNumber, "SerialNumber", serialNumber, "Manufacturer", manufacturer,
430 "RevisionCode", revisionCode, "Present", present, "MemoryTotalWidth",
431 memoryTotalWidth, "ECC", ecc, "FormFactor", formFactor,
432 "AllowedSpeedsMT", allowedSpeedsMT, "MemoryAttributes",
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200433 memoryAttributes, "MemoryConfiguredSpeedInMhz",
434 memoryConfiguredSpeedInMhz, "MemoryType", memoryType, "Channel",
435 channel, "MemoryController", memoryController, "Slot", slot, "Socket",
436 socket, "SparePartNumber", sparePartNumber, "Model", model,
437 "LocationCode", locationCode);
438
439 if (!success)
Nan Zhou9a5acea2022-05-17 21:12:43 +0000440 {
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200441 messages::internalError(aResp->res);
442 return;
443 }
Nan Zhou9a5acea2022-05-17 21:12:43 +0000444
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200445 if (memoryDataWidth != nullptr)
446 {
447 aResp->res.jsonValue[jsonPtr]["DataWidthBits"] = *memoryDataWidth;
448 }
Nan Zhou9a5acea2022-05-17 21:12:43 +0000449
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200450 if (memorySizeInKB != nullptr)
451 {
452 aResp->res.jsonValue[jsonPtr]["CapacityMiB"] = (*memorySizeInKB >> 10);
453 }
Nan Zhou9a5acea2022-05-17 21:12:43 +0000454
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200455 if (partNumber != nullptr)
456 {
457 aResp->res.jsonValue[jsonPtr]["PartNumber"] = *partNumber;
458 }
Nan Zhou9a5acea2022-05-17 21:12:43 +0000459
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200460 if (serialNumber != nullptr)
461 {
462 aResp->res.jsonValue[jsonPtr]["SerialNumber"] = *serialNumber;
463 }
464
465 if (manufacturer != nullptr)
466 {
467 aResp->res.jsonValue[jsonPtr]["Manufacturer"] = *manufacturer;
468 }
469
470 if (revisionCode != nullptr)
471 {
472 aResp->res.jsonValue[jsonPtr]["FirmwareRevision"] =
473 std::to_string(*revisionCode);
474 }
475
476 if (present != nullptr && !*present)
477 {
478 aResp->res.jsonValue[jsonPtr]["Status"]["State"] = "Absent";
479 }
480
481 if (memoryTotalWidth != nullptr)
482 {
483 aResp->res.jsonValue[jsonPtr]["BusWidthBits"] = *memoryTotalWidth;
484 }
485
486 if (ecc != nullptr)
487 {
488 constexpr const std::array<const char*, 4> values{
489 "NoECC", "SingleBitECC", "MultiBitECC", "AddressParity"};
490
491 for (const char* v : values)
Nan Zhou9a5acea2022-05-17 21:12:43 +0000492 {
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200493 if (ecc->ends_with(v))
Nan Zhou9a5acea2022-05-17 21:12:43 +0000494 {
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200495 aResp->res.jsonValue[jsonPtr]["ErrorCorrection"] = v;
496 break;
Nan Zhou9a5acea2022-05-17 21:12:43 +0000497 }
Nan Zhou9a5acea2022-05-17 21:12:43 +0000498 }
499 }
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200500
501 if (formFactor != nullptr)
502 {
503 constexpr const std::array<const char*, 11> values{
504 "RDIMM", "UDIMM", "SO_DIMM", "LRDIMM",
505 "Mini_RDIMM", "Mini_UDIMM", "SO_RDIMM_72b", "SO_UDIMM_72b",
506 "SO_DIMM_16b", "SO_DIMM_32b", "Die"};
507
508 for (const char* v : values)
509 {
510 if (formFactor->ends_with(v))
511 {
512 aResp->res.jsonValue[jsonPtr]["BaseModuleType"] = v;
513 break;
514 }
515 }
516 }
517
518 if (allowedSpeedsMT != nullptr)
519 {
520 nlohmann::json& jValue =
521 aResp->res.jsonValue[jsonPtr]["AllowedSpeedsMHz"];
522 jValue = nlohmann::json::array();
523 for (uint16_t subVal : *allowedSpeedsMT)
524 {
525 jValue.push_back(subVal);
526 }
527 }
528
529 if (memoryAttributes != nullptr)
530 {
531 aResp->res.jsonValue[jsonPtr]["RankCount"] =
532 static_cast<uint64_t>(*memoryAttributes);
533 }
534
535 if (memoryConfiguredSpeedInMhz != nullptr)
536 {
537 aResp->res.jsonValue[jsonPtr]["OperatingSpeedMhz"] =
538 *memoryConfiguredSpeedInMhz;
539 }
540
541 if (memoryType != nullptr)
542 {
543 std::string memoryDeviceType =
544 translateMemoryTypeToRedfish(*memoryType);
545 // Values like "Unknown" or "Other" will return empty
546 // so just leave off
547 if (!memoryDeviceType.empty())
548 {
549 aResp->res.jsonValue[jsonPtr]["MemoryDeviceType"] =
550 memoryDeviceType;
551 }
552 if (memoryType->find("DDR") != std::string::npos)
553 {
554 aResp->res.jsonValue[jsonPtr]["MemoryType"] = "DRAM";
555 }
556 else if (memoryType->ends_with("Logical"))
557 {
558 aResp->res.jsonValue[jsonPtr]["MemoryType"] = "IntelOptane";
559 }
560 }
561
562 if (channel != nullptr)
563 {
564 aResp->res.jsonValue[jsonPtr]["MemoryLocation"]["Channel"] = *channel;
565 }
566
567 if (memoryController != nullptr)
568 {
569 aResp->res.jsonValue[jsonPtr]["MemoryLocation"]["MemoryController"] =
570 *memoryController;
571 }
572
573 if (slot != nullptr)
574 {
575 aResp->res.jsonValue[jsonPtr]["MemoryLocation"]["Slot"] = *slot;
576 }
577
578 if (socket != nullptr)
579 {
580 aResp->res.jsonValue[jsonPtr]["MemoryLocation"]["Socket"] = *socket;
581 }
582
583 if (sparePartNumber != nullptr)
584 {
585 aResp->res.jsonValue[jsonPtr]["SparePartNumber"] = *sparePartNumber;
586 }
587
588 if (model != nullptr)
589 {
590 aResp->res.jsonValue[jsonPtr]["Model"] = *model;
591 }
592
593 if (locationCode != nullptr)
594 {
595 aResp->res
596 .jsonValue[jsonPtr]["Location"]["PartLocation"]["ServiceLabel"] =
597 *locationCode;
598 }
599
600 getPersistentMemoryProperties(aResp, properties, jsonPtr);
Nan Zhou9a5acea2022-05-17 21:12:43 +0000601}
602
zhanghch058d1b46d2021-04-01 11:18:24 +0800603inline void getDimmDataByService(std::shared_ptr<bmcweb::AsyncResp> aResp,
Ed Tanous80789c82020-08-19 09:19:09 -0700604 const std::string& dimmId,
605 const std::string& service,
606 const std::string& objPath)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200607{
James Feist35e257a2020-06-05 13:30:51 -0700608 auto health = std::make_shared<HealthPopulate>(aResp);
609 health->selfPath = objPath;
610 health->populate();
611
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200612 BMCWEB_LOG_DEBUG << "Get available system components.";
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200613 sdbusplus::asio::getAllProperties(
614 *crow::connections::systemBus, service, objPath, "",
Ed Tanousb9d36b42022-02-26 21:42:46 -0800615 [dimmId, aResp{std::move(aResp)}](
616 const boost::system::error_code ec,
617 const dbus::utility::DBusPropertiesMap& properties) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700618 if (ec)
619 {
620 BMCWEB_LOG_DEBUG << "DBUS response error";
621 messages::internalError(aResp->res);
622 return;
623 }
Nan Zhoud7f04fd2022-05-01 01:11:07 +0000624 assembleDimmProperties(dimmId, aResp, properties, ""_json_pointer);
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200625 });
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200626}
627
Nan Zhouef00d7d2022-05-20 21:22:32 +0000628inline void assembleDimmPartitionData(
629 const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Nan Zhoud7f04fd2022-05-01 01:11:07 +0000630 const dbus::utility::DBusPropertiesMap& properties,
631 const nlohmann::json::json_pointer& regionPtr)
Nan Zhouef00d7d2022-05-20 21:22:32 +0000632{
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200633 const std::string* memoryClassification = nullptr;
634 const uint64_t* offsetInKiB = nullptr;
635 const std::string* partitionId = nullptr;
636 const bool* passphraseState = nullptr;
637 const uint64_t* sizeInKiB = nullptr;
638
639 const bool success = sdbusplus::unpackPropertiesNoThrow(
640 dbus_utils::UnpackErrorPrinter(), properties, "MemoryClassification",
641 memoryClassification, "OffsetInKiB", offsetInKiB, "PartitionId",
642 partitionId, "PassphraseState", passphraseState, "SizeInKiB",
643 sizeInKiB);
644
645 if (!success)
Nan Zhouef00d7d2022-05-20 21:22:32 +0000646 {
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200647 messages::internalError(aResp->res);
648 return;
Nan Zhouef00d7d2022-05-20 21:22:32 +0000649 }
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200650
651 nlohmann::json::object_t partition;
652
653 if (memoryClassification != nullptr)
654 {
655 partition["MemoryClassification"] = *memoryClassification;
656 }
657
658 if (offsetInKiB != nullptr)
659 {
660 partition["OffsetMiB"] = (*offsetInKiB >> 10);
661 }
662
663 if (partitionId != nullptr)
664 {
665 partition["RegionId"] = *partitionId;
666 }
667
668 if (passphraseState != nullptr)
669 {
670 partition["PassphraseEnabled"] = *passphraseState;
671 }
672
673 if (sizeInKiB != nullptr)
674 {
675 partition["SizeMiB"] = (*sizeInKiB >> 10);
676 }
677
Nan Zhoud7f04fd2022-05-01 01:11:07 +0000678 aResp->res.jsonValue[regionPtr].emplace_back(std::move(partition));
Nan Zhouef00d7d2022-05-20 21:22:32 +0000679}
680
zhanghch058d1b46d2021-04-01 11:18:24 +0800681inline void getDimmPartitionData(std::shared_ptr<bmcweb::AsyncResp> aResp,
Ed Tanous23a21a12020-07-25 04:45:05 +0000682 const std::string& service,
683 const std::string& path)
James Feist45094ad2020-04-29 14:02:30 -0700684{
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200685 sdbusplus::asio::getAllProperties(
686 *crow::connections::systemBus, service, path,
687 "xyz.openbmc_project.Inventory.Item.PersistentMemory.Partition",
James Feist45094ad2020-04-29 14:02:30 -0700688 [aResp{std::move(aResp)}](
689 const boost::system::error_code ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -0800690 const dbus::utility::DBusPropertiesMap& properties) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700691 if (ec)
692 {
693 BMCWEB_LOG_DEBUG << "DBUS response error";
694 messages::internalError(aResp->res);
James Feist45094ad2020-04-29 14:02:30 -0700695
Ed Tanous002d39b2022-05-31 08:59:27 -0700696 return;
697 }
Nan Zhoud7f04fd2022-05-01 01:11:07 +0000698 nlohmann::json::json_pointer regionPtr = "/Regions"_json_pointer;
699 assembleDimmPartitionData(aResp, properties, regionPtr);
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200700 }
James Feist45094ad2020-04-29 14:02:30 -0700701
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200702 );
James Feist45094ad2020-04-29 14:02:30 -0700703}
704
zhanghch058d1b46d2021-04-01 11:18:24 +0800705inline void getDimmData(std::shared_ptr<bmcweb::AsyncResp> aResp,
Ed Tanous23a21a12020-07-25 04:45:05 +0000706 const std::string& dimmId)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200707{
708 BMCWEB_LOG_DEBUG << "Get available system dimm resources.";
709 crow::connections::systemBus->async_method_call(
Ed Tanous029573d2019-02-01 10:57:49 -0800710 [dimmId, aResp{std::move(aResp)}](
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200711 const boost::system::error_code ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -0800712 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700713 if (ec)
714 {
715 BMCWEB_LOG_DEBUG << "DBUS response error";
716 messages::internalError(aResp->res);
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200717
Ed Tanous002d39b2022-05-31 08:59:27 -0700718 return;
719 }
720 bool found = false;
Nan Zhou76686dc2022-06-17 23:01:51 +0000721 for (const auto& [rawPath, object] : subtree)
Ed Tanous002d39b2022-05-31 08:59:27 -0700722 {
Nan Zhou76686dc2022-06-17 23:01:51 +0000723 sdbusplus::message::object_path path(rawPath);
724 for (const auto& [service, interfaces] : object)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200725 {
Nan Zhou76686dc2022-06-17 23:01:51 +0000726 for (const auto& interface : interfaces)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200727 {
Nan Zhou76686dc2022-06-17 23:01:51 +0000728 if (interface ==
729 "xyz.openbmc_project.Inventory.Item.Dimm" &&
730 path.filename() == dimmId)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200731 {
Nan Zhou76686dc2022-06-17 23:01:51 +0000732 getDimmDataByService(aResp, dimmId, service, rawPath);
733 found = true;
734 }
James Feist45094ad2020-04-29 14:02:30 -0700735
Nan Zhou76686dc2022-06-17 23:01:51 +0000736 // partitions are separate as there can be multiple
737 // per
738 // device, i.e.
739 // /xyz/openbmc_project/Inventory/Item/Dimm1/Partition1
740 // /xyz/openbmc_project/Inventory/Item/Dimm1/Partition2
741 if (interface ==
742 "xyz.openbmc_project.Inventory.Item.PersistentMemory.Partition" &&
743 path.parent_path().filename() == dimmId)
744 {
745 getDimmPartitionData(aResp, service, rawPath);
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200746 }
747 }
748 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700749 }
750 // Object not found
751 if (!found)
752 {
753 messages::resourceNotFound(aResp->res, "Memory", dimmId);
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200754 return;
Ed Tanous002d39b2022-05-31 08:59:27 -0700755 }
756 // Set @odata only if object is found
757 aResp->res.jsonValue["@odata.type"] = "#Memory.v1_11_0.Memory";
758 aResp->res.jsonValue["@odata.id"] =
759 "/redfish/v1/Systems/system/Memory/" + dimmId;
760 return;
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200761 },
762 "xyz.openbmc_project.ObjectMapper",
763 "/xyz/openbmc_project/object_mapper",
764 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
Ed Tanous271584a2019-07-09 16:24:22 -0700765 "/xyz/openbmc_project/inventory", 0,
James Feist45094ad2020-04-29 14:02:30 -0700766 std::array<const char*, 2>{
767 "xyz.openbmc_project.Inventory.Item.Dimm",
768 "xyz.openbmc_project.Inventory.Item.PersistentMemory.Partition"});
Ed Tanous271584a2019-07-09 16:24:22 -0700769}
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200770
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700771inline void requestRoutesMemoryCollection(App& app)
Ed Tanous029573d2019-02-01 10:57:49 -0800772{
Ed Tanous029573d2019-02-01 10:57:49 -0800773 /**
774 * Functions triggers appropriate requests on DBus
775 */
Ed Tanous22d268c2022-05-19 09:39:07 -0700776 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Memory/")
Ed Tanoused398212021-06-09 17:05:54 -0700777 .privileges(redfish::privileges::getMemoryCollection)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700778 .methods(boost::beast::http::verb::get)(
Ed Tanous45ca1b82022-03-25 13:07:27 -0700779 [&app](const crow::Request& req,
Ed Tanous22d268c2022-05-19 09:39:07 -0700780 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
781 const std::string& systemName) {
Carson Labrado3ba00072022-06-06 19:40:56 +0000782 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -0700783 {
784 return;
785 }
Ed Tanous22d268c2022-05-19 09:39:07 -0700786 if (systemName != "system")
787 {
788 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
789 systemName);
790 return;
791 }
792
Ed Tanous002d39b2022-05-31 08:59:27 -0700793 asyncResp->res.jsonValue["@odata.type"] =
794 "#MemoryCollection.MemoryCollection";
795 asyncResp->res.jsonValue["Name"] = "Memory Module Collection";
796 asyncResp->res.jsonValue["@odata.id"] =
797 "/redfish/v1/Systems/system/Memory";
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200798
George Liu7a1dbc42022-12-07 16:03:22 +0800799 constexpr std::array<std::string_view, 1> interfaces{
800 "xyz.openbmc_project.Inventory.Item.Dimm"};
Ed Tanous002d39b2022-05-31 08:59:27 -0700801 collection_util::getCollectionMembers(
Willy Tuae9031f2022-09-27 05:48:07 +0000802 asyncResp, boost::urls::url("/redfish/v1/Systems/system/Memory"),
George Liu7a1dbc42022-12-07 16:03:22 +0800803 interfaces);
Ed Tanous002d39b2022-05-31 08:59:27 -0700804 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700805}
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200806
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700807inline void requestRoutesMemory(App& app)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200808{
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200809 /**
810 * Functions triggers appropriate requests on DBus
811 */
Ed Tanous22d268c2022-05-19 09:39:07 -0700812 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Memory/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -0700813 .privileges(redfish::privileges::getMemory)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700814 .methods(boost::beast::http::verb::get)(
Ed Tanous45ca1b82022-03-25 13:07:27 -0700815 [&app](const crow::Request& req,
816 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous22d268c2022-05-19 09:39:07 -0700817 const std::string& systemName, const std::string& dimmId) {
Carson Labrado3ba00072022-06-06 19:40:56 +0000818 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -0700819 {
820 return;
821 }
Ed Tanous22d268c2022-05-19 09:39:07 -0700822 if (systemName != "system")
823 {
824 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
825 systemName);
826 return;
827 }
828
Ed Tanous002d39b2022-05-31 08:59:27 -0700829 getDimmData(asyncResp, dimmId);
830 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700831}
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200832
833} // namespace redfish