xref: /openbmc/bmcweb/features/redfish/lib/memory.hpp (revision 76686dcc74002493e22d72e24db9d3326b3a63ed)
1ac6a4445SGunnar Mills /*
2ac6a4445SGunnar Mills // Copyright (c) 2018 Intel Corporation
3ac6a4445SGunnar Mills //
4ac6a4445SGunnar Mills // Licensed under the Apache License, Version 2.0 (the "License");
5ac6a4445SGunnar Mills // you may not use this file except in compliance with the License.
6ac6a4445SGunnar Mills // You may obtain a copy of the License at
7ac6a4445SGunnar Mills //
8ac6a4445SGunnar Mills //      http://www.apache.org/licenses/LICENSE-2.0
9ac6a4445SGunnar Mills //
10ac6a4445SGunnar Mills // Unless required by applicable law or agreed to in writing, software
11ac6a4445SGunnar Mills // distributed under the License is distributed on an "AS IS" BASIS,
12ac6a4445SGunnar Mills // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13ac6a4445SGunnar Mills // See the License for the specific language governing permissions and
14ac6a4445SGunnar Mills // limitations under the License.
15ac6a4445SGunnar Mills */
16ac6a4445SGunnar Mills #pragma once
17ac6a4445SGunnar Mills 
18ac6a4445SGunnar Mills #include "health.hpp"
19ac6a4445SGunnar Mills 
207e860f15SJohn Edward Broadbent #include <app.hpp>
217267c21dSSui Chen #include <boost/algorithm/string.hpp>
22168e20c1SEd Tanous #include <dbus_utility.hpp>
23d7f04fd9SNan Zhou #include <nlohmann/json.hpp>
2445ca1b86SEd Tanous #include <query.hpp>
25ed398213SEd Tanous #include <registries/privilege_registry.hpp>
26ac6a4445SGunnar Mills #include <utils/collection.hpp>
27f201ffb4SEd Tanous #include <utils/hex_utils.hpp>
28ac6a4445SGunnar Mills #include <utils/json_utils.hpp>
29ac6a4445SGunnar Mills 
30ac6a4445SGunnar Mills namespace redfish
31ac6a4445SGunnar Mills {
32ac6a4445SGunnar Mills 
33313efb1cSGunnar Mills inline std::string translateMemoryTypeToRedfish(const std::string& memoryType)
34313efb1cSGunnar Mills {
35313efb1cSGunnar Mills     if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR")
36313efb1cSGunnar Mills     {
37313efb1cSGunnar Mills         return "DDR";
38313efb1cSGunnar Mills     }
39313efb1cSGunnar Mills     if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR2")
40313efb1cSGunnar Mills     {
41313efb1cSGunnar Mills         return "DDR2";
42313efb1cSGunnar Mills     }
43313efb1cSGunnar Mills     if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR3")
44313efb1cSGunnar Mills     {
45313efb1cSGunnar Mills         return "DDR3";
46313efb1cSGunnar Mills     }
47313efb1cSGunnar Mills     if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR4")
48313efb1cSGunnar Mills     {
49313efb1cSGunnar Mills         return "DDR4";
50313efb1cSGunnar Mills     }
51313efb1cSGunnar Mills     if (memoryType ==
52313efb1cSGunnar Mills         "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR4E_SDRAM")
53313efb1cSGunnar Mills     {
54313efb1cSGunnar Mills         return "DDR4E_SDRAM";
55313efb1cSGunnar Mills     }
5611a2f0f0SMansi Joshi     if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR5")
5711a2f0f0SMansi Joshi     {
5811a2f0f0SMansi Joshi         return "DDR5";
5911a2f0f0SMansi Joshi     }
60313efb1cSGunnar Mills     if (memoryType ==
61313efb1cSGunnar Mills         "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.LPDDR4_SDRAM")
62313efb1cSGunnar Mills     {
63313efb1cSGunnar Mills         return "LPDDR4_SDRAM";
64313efb1cSGunnar Mills     }
65313efb1cSGunnar Mills     if (memoryType ==
66313efb1cSGunnar Mills         "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.LPDDR3_SDRAM")
67313efb1cSGunnar Mills     {
68313efb1cSGunnar Mills         return "LPDDR3_SDRAM";
69313efb1cSGunnar Mills     }
70313efb1cSGunnar Mills     if (memoryType ==
71313efb1cSGunnar Mills         "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR2_SDRAM_FB_DIMM")
72313efb1cSGunnar Mills     {
73313efb1cSGunnar Mills         return "DDR2_SDRAM_FB_DIMM";
74313efb1cSGunnar Mills     }
750fda0f12SGeorge Liu     if (memoryType ==
760fda0f12SGeorge Liu         "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR2_SDRAM_FB_DIMM_PROB")
77313efb1cSGunnar Mills     {
78313efb1cSGunnar Mills         return "DDR2_SDRAM_FB_DIMM_PROBE";
79313efb1cSGunnar Mills     }
80313efb1cSGunnar Mills     if (memoryType ==
81313efb1cSGunnar Mills         "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR_SGRAM")
82313efb1cSGunnar Mills     {
83313efb1cSGunnar Mills         return "DDR_SGRAM";
84313efb1cSGunnar Mills     }
85313efb1cSGunnar Mills     if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.ROM")
86313efb1cSGunnar Mills     {
87313efb1cSGunnar Mills         return "ROM";
88313efb1cSGunnar Mills     }
89313efb1cSGunnar Mills     if (memoryType ==
90313efb1cSGunnar Mills         "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.SDRAM")
91313efb1cSGunnar Mills     {
92313efb1cSGunnar Mills         return "SDRAM";
93313efb1cSGunnar Mills     }
94313efb1cSGunnar Mills     if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.EDO")
95313efb1cSGunnar Mills     {
96313efb1cSGunnar Mills         return "EDO";
97313efb1cSGunnar Mills     }
98313efb1cSGunnar Mills     if (memoryType ==
99313efb1cSGunnar Mills         "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.FastPageMode")
100313efb1cSGunnar Mills     {
101313efb1cSGunnar Mills         return "FastPageMode";
102313efb1cSGunnar Mills     }
103313efb1cSGunnar Mills     if (memoryType ==
104313efb1cSGunnar Mills         "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.PipelinedNibble")
105313efb1cSGunnar Mills     {
106313efb1cSGunnar Mills         return "PipelinedNibble";
107313efb1cSGunnar Mills     }
108313efb1cSGunnar Mills     if (memoryType ==
109313efb1cSGunnar Mills         "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.Logical")
110313efb1cSGunnar Mills     {
111313efb1cSGunnar Mills         return "Logical";
112313efb1cSGunnar Mills     }
113313efb1cSGunnar Mills     if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.HBM")
114313efb1cSGunnar Mills     {
115313efb1cSGunnar Mills         return "HBM";
116313efb1cSGunnar Mills     }
117313efb1cSGunnar Mills     if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.HBM2")
118313efb1cSGunnar Mills     {
119313efb1cSGunnar Mills         return "HBM2";
120313efb1cSGunnar Mills     }
121313efb1cSGunnar Mills     // This is values like Other or Unknown
122313efb1cSGunnar Mills     // Also D-Bus values:
123313efb1cSGunnar Mills     // DRAM
124313efb1cSGunnar Mills     // EDRAM
125313efb1cSGunnar Mills     // VRAM
126313efb1cSGunnar Mills     // SRAM
127313efb1cSGunnar Mills     // RAM
128313efb1cSGunnar Mills     // FLASH
129313efb1cSGunnar Mills     // EEPROM
130313efb1cSGunnar Mills     // FEPROM
131313efb1cSGunnar Mills     // EPROM
132313efb1cSGunnar Mills     // CDRAM
133313efb1cSGunnar Mills     // ThreeDRAM
134313efb1cSGunnar Mills     // RDRAM
135313efb1cSGunnar Mills     // FBD2
136313efb1cSGunnar Mills     // LPDDR_SDRAM
137313efb1cSGunnar Mills     // LPDDR2_SDRAM
13811a2f0f0SMansi Joshi     // LPDDR5_SDRAM
139313efb1cSGunnar Mills     return "";
140313efb1cSGunnar Mills }
141313efb1cSGunnar Mills 
142168e20c1SEd Tanous inline void dimmPropToHex(
143168e20c1SEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& aResp, const char* key,
144d7f04fd9SNan Zhou     const std::pair<std::string, dbus::utility::DbusVariantType>& property,
145d7f04fd9SNan Zhou     const nlohmann::json::json_pointer& jsonPtr)
146ac6a4445SGunnar Mills {
147ac6a4445SGunnar Mills     const uint16_t* value = std::get_if<uint16_t>(&property.second);
148ac6a4445SGunnar Mills     if (value == nullptr)
149ac6a4445SGunnar Mills     {
150ac6a4445SGunnar Mills         messages::internalError(aResp->res);
151ac6a4445SGunnar Mills         BMCWEB_LOG_DEBUG << "Invalid property type for " << property.first;
152ac6a4445SGunnar Mills         return;
153ac6a4445SGunnar Mills     }
154d7f04fd9SNan Zhou     aResp->res.jsonValue[jsonPtr][key] = "0x" + intToHexString(*value, 4);
155ac6a4445SGunnar Mills }
156ac6a4445SGunnar Mills 
1578d1b46d7Szhanghch05 inline void getPersistentMemoryProperties(
1588d1b46d7Szhanghch05     const std::shared_ptr<bmcweb::AsyncResp>& aResp,
159d7f04fd9SNan Zhou     const std::pair<std::string, dbus::utility::DbusVariantType>& property,
160d7f04fd9SNan Zhou     const nlohmann::json::json_pointer& jsonPtr)
161ac6a4445SGunnar Mills {
162ac6a4445SGunnar Mills     if (property.first == "ModuleManufacturerID")
163ac6a4445SGunnar Mills     {
164d7f04fd9SNan Zhou         dimmPropToHex(aResp, "ModuleManufacturerID", property, jsonPtr);
165ac6a4445SGunnar Mills     }
166ac6a4445SGunnar Mills     else if (property.first == "ModuleProductID")
167ac6a4445SGunnar Mills     {
168d7f04fd9SNan Zhou         dimmPropToHex(aResp, "ModuleProductID", property, jsonPtr);
169ac6a4445SGunnar Mills     }
170ac6a4445SGunnar Mills     else if (property.first == "SubsystemVendorID")
171ac6a4445SGunnar Mills     {
172ac6a4445SGunnar Mills         dimmPropToHex(aResp, "MemorySubsystemControllerManufacturerID",
173d7f04fd9SNan Zhou                       property, jsonPtr);
174ac6a4445SGunnar Mills     }
175ac6a4445SGunnar Mills     else if (property.first == "SubsystemDeviceID")
176ac6a4445SGunnar Mills     {
177d7f04fd9SNan Zhou         dimmPropToHex(aResp, "MemorySubsystemControllerProductID", property,
178d7f04fd9SNan Zhou                       jsonPtr);
179ac6a4445SGunnar Mills     }
180ac6a4445SGunnar Mills     else if (property.first == "VolatileRegionSizeLimitInKiB")
181ac6a4445SGunnar Mills     {
182ac6a4445SGunnar Mills         const uint64_t* value = std::get_if<uint64_t>(&property.second);
183ac6a4445SGunnar Mills 
184ac6a4445SGunnar Mills         if (value == nullptr)
185ac6a4445SGunnar Mills         {
186ac6a4445SGunnar Mills             messages::internalError(aResp->res);
1870fda0f12SGeorge Liu             BMCWEB_LOG_DEBUG
1880fda0f12SGeorge Liu                 << "Invalid property type for VolatileRegionSizeLimitKiB";
189601af5edSChicago Duan             return;
190ac6a4445SGunnar Mills         }
191d7f04fd9SNan Zhou         aResp->res.jsonValue[jsonPtr]["VolatileRegionSizeLimitMiB"] =
192d7f04fd9SNan Zhou             (*value) >> 10;
193ac6a4445SGunnar Mills     }
194ac6a4445SGunnar Mills     else if (property.first == "PmRegionSizeLimitInKiB")
195ac6a4445SGunnar Mills     {
196ac6a4445SGunnar Mills         const uint64_t* value = std::get_if<uint64_t>(&property.second);
197ac6a4445SGunnar Mills 
198ac6a4445SGunnar Mills         if (value == nullptr)
199ac6a4445SGunnar Mills         {
200ac6a4445SGunnar Mills             messages::internalError(aResp->res);
20180badf7cSJiaqing Zhao             BMCWEB_LOG_DEBUG << "Invalid property type for PmRegioSizeLimitKiB";
202601af5edSChicago Duan             return;
203ac6a4445SGunnar Mills         }
204d7f04fd9SNan Zhou         aResp->res.jsonValue[jsonPtr]["PersistentRegionSizeLimitMiB"] =
205d7f04fd9SNan Zhou             (*value) >> 10;
206ac6a4445SGunnar Mills     }
207ac6a4445SGunnar Mills     else if (property.first == "VolatileSizeInKiB")
208ac6a4445SGunnar Mills     {
209ac6a4445SGunnar Mills         const uint64_t* value = std::get_if<uint64_t>(&property.second);
210ac6a4445SGunnar Mills 
211ac6a4445SGunnar Mills         if (value == nullptr)
212ac6a4445SGunnar Mills         {
213ac6a4445SGunnar Mills             messages::internalError(aResp->res);
21480badf7cSJiaqing Zhao             BMCWEB_LOG_DEBUG << "Invalid property type for VolatileSizeInKiB";
215601af5edSChicago Duan             return;
216ac6a4445SGunnar Mills         }
217d7f04fd9SNan Zhou         aResp->res.jsonValue[jsonPtr]["VolatileSizeMiB"] = (*value) >> 10;
218ac6a4445SGunnar Mills     }
219ac6a4445SGunnar Mills     else if (property.first == "PmSizeInKiB")
220ac6a4445SGunnar Mills     {
221ac6a4445SGunnar Mills         const uint64_t* value = std::get_if<uint64_t>(&property.second);
222ac6a4445SGunnar Mills         if (value == nullptr)
223ac6a4445SGunnar Mills         {
224ac6a4445SGunnar Mills             messages::internalError(aResp->res);
225ac6a4445SGunnar Mills             BMCWEB_LOG_DEBUG << "Invalid property type for PmSizeInKiB";
226601af5edSChicago Duan             return;
227ac6a4445SGunnar Mills         }
228d7f04fd9SNan Zhou         aResp->res.jsonValue[jsonPtr]["NonVolatileSizeMiB"] = (*value) >> 10;
229ac6a4445SGunnar Mills     }
230ac6a4445SGunnar Mills     else if (property.first == "CacheSizeInKB")
231ac6a4445SGunnar Mills     {
232ac6a4445SGunnar Mills         const uint64_t* value = std::get_if<uint64_t>(&property.second);
233ac6a4445SGunnar Mills         if (value == nullptr)
234ac6a4445SGunnar Mills         {
235ac6a4445SGunnar Mills             messages::internalError(aResp->res);
236ac6a4445SGunnar Mills             BMCWEB_LOG_DEBUG << "Invalid property type for CacheSizeInKB";
237601af5edSChicago Duan             return;
238ac6a4445SGunnar Mills         }
239d7f04fd9SNan Zhou         aResp->res.jsonValue[jsonPtr]["CacheSizeMiB"] = (*value >> 10);
240ac6a4445SGunnar Mills     }
241ac6a4445SGunnar Mills 
242ac6a4445SGunnar Mills     else if (property.first == "VoltaileRegionMaxSizeInKib")
243ac6a4445SGunnar Mills     {
244ac6a4445SGunnar Mills         const uint64_t* value = std::get_if<uint64_t>(&property.second);
245ac6a4445SGunnar Mills 
246ac6a4445SGunnar Mills         if (value == nullptr)
247ac6a4445SGunnar Mills         {
248ac6a4445SGunnar Mills             messages::internalError(aResp->res);
2490fda0f12SGeorge Liu             BMCWEB_LOG_DEBUG
2500fda0f12SGeorge Liu                 << "Invalid property type for VolatileRegionMaxSizeInKib";
251601af5edSChicago Duan             return;
252ac6a4445SGunnar Mills         }
253d7f04fd9SNan Zhou         aResp->res.jsonValue[jsonPtr]["VolatileRegionSizeMaxMiB"] =
254d7f04fd9SNan Zhou             (*value) >> 10;
255ac6a4445SGunnar Mills     }
256ac6a4445SGunnar Mills     else if (property.first == "PmRegionMaxSizeInKiB")
257ac6a4445SGunnar Mills     {
258ac6a4445SGunnar Mills         const uint64_t* value = std::get_if<uint64_t>(&property.second);
259ac6a4445SGunnar Mills 
260ac6a4445SGunnar Mills         if (value == nullptr)
261ac6a4445SGunnar Mills         {
262ac6a4445SGunnar Mills             messages::internalError(aResp->res);
263ac6a4445SGunnar Mills             BMCWEB_LOG_DEBUG
264ac6a4445SGunnar Mills                 << "Invalid property type for PmRegionMaxSizeInKiB";
265601af5edSChicago Duan             return;
266ac6a4445SGunnar Mills         }
267d7f04fd9SNan Zhou         aResp->res.jsonValue[jsonPtr]["PersistentRegionSizeMaxMiB"] =
268d7f04fd9SNan Zhou             (*value) >> 10;
269ac6a4445SGunnar Mills     }
270ac6a4445SGunnar Mills     else if (property.first == "AllocationIncrementInKiB")
271ac6a4445SGunnar Mills     {
272ac6a4445SGunnar Mills         const uint64_t* value = std::get_if<uint64_t>(&property.second);
273ac6a4445SGunnar Mills 
274ac6a4445SGunnar Mills         if (value == nullptr)
275ac6a4445SGunnar Mills         {
276ac6a4445SGunnar Mills             messages::internalError(aResp->res);
2770fda0f12SGeorge Liu             BMCWEB_LOG_DEBUG
2780fda0f12SGeorge Liu                 << "Invalid property type for AllocationIncrementInKiB";
279601af5edSChicago Duan             return;
280ac6a4445SGunnar Mills         }
281d7f04fd9SNan Zhou         aResp->res.jsonValue[jsonPtr]["AllocationIncrementMiB"] =
282d7f04fd9SNan Zhou             (*value) >> 10;
283ac6a4445SGunnar Mills     }
284ac6a4445SGunnar Mills     else if (property.first == "AllocationAlignmentInKiB")
285ac6a4445SGunnar Mills     {
286ac6a4445SGunnar Mills         const uint64_t* value = std::get_if<uint64_t>(&property.second);
287ac6a4445SGunnar Mills 
288ac6a4445SGunnar Mills         if (value == nullptr)
289ac6a4445SGunnar Mills         {
290ac6a4445SGunnar Mills             messages::internalError(aResp->res);
2910fda0f12SGeorge Liu             BMCWEB_LOG_DEBUG
2920fda0f12SGeorge Liu                 << "Invalid property type for AllocationAlignmentInKiB";
293601af5edSChicago Duan             return;
294ac6a4445SGunnar Mills         }
295d7f04fd9SNan Zhou         aResp->res.jsonValue[jsonPtr]["AllocationAlignmentMiB"] =
296d7f04fd9SNan Zhou             (*value) >> 10;
297ac6a4445SGunnar Mills     }
298ac6a4445SGunnar Mills     else if (property.first == "VolatileRegionNumberLimit")
299ac6a4445SGunnar Mills     {
300ac6a4445SGunnar Mills         const uint64_t* value = std::get_if<uint64_t>(&property.second);
301ac6a4445SGunnar Mills         if (value == nullptr)
302ac6a4445SGunnar Mills         {
303ac6a4445SGunnar Mills             messages::internalError(aResp->res);
304601af5edSChicago Duan             return;
305ac6a4445SGunnar Mills         }
306d7f04fd9SNan Zhou         aResp->res.jsonValue[jsonPtr]["VolatileRegionNumberLimit"] = *value;
307ac6a4445SGunnar Mills     }
308ac6a4445SGunnar Mills     else if (property.first == "PmRegionNumberLimit")
309ac6a4445SGunnar Mills     {
310ac6a4445SGunnar Mills         const uint64_t* value = std::get_if<uint64_t>(&property.second);
311ac6a4445SGunnar Mills         if (value == nullptr)
312ac6a4445SGunnar Mills         {
313ac6a4445SGunnar Mills             messages::internalError(aResp->res);
314601af5edSChicago Duan             return;
315ac6a4445SGunnar Mills         }
316d7f04fd9SNan Zhou         aResp->res.jsonValue[jsonPtr]["PersistentRegionNumberLimit"] = *value;
317ac6a4445SGunnar Mills     }
318ac6a4445SGunnar Mills     else if (property.first == "SpareDeviceCount")
319ac6a4445SGunnar Mills     {
320ac6a4445SGunnar Mills         const uint64_t* value = std::get_if<uint64_t>(&property.second);
321ac6a4445SGunnar Mills         if (value == nullptr)
322ac6a4445SGunnar Mills         {
323ac6a4445SGunnar Mills             messages::internalError(aResp->res);
324601af5edSChicago Duan             return;
325ac6a4445SGunnar Mills         }
326d7f04fd9SNan Zhou         aResp->res.jsonValue[jsonPtr]["SpareDeviceCount"] = *value;
327ac6a4445SGunnar Mills     }
328ac6a4445SGunnar Mills     else if (property.first == "IsSpareDeviceInUse")
329ac6a4445SGunnar Mills     {
330ac6a4445SGunnar Mills         const bool* value = std::get_if<bool>(&property.second);
331ac6a4445SGunnar Mills         if (value == nullptr)
332ac6a4445SGunnar Mills         {
333ac6a4445SGunnar Mills             messages::internalError(aResp->res);
334601af5edSChicago Duan             return;
335ac6a4445SGunnar Mills         }
336d7f04fd9SNan Zhou         aResp->res.jsonValue[jsonPtr]["IsSpareDeviceEnabled"] = *value;
337ac6a4445SGunnar Mills     }
338ac6a4445SGunnar Mills     else if (property.first == "IsRankSpareEnabled")
339ac6a4445SGunnar Mills     {
340ac6a4445SGunnar Mills         const bool* value = std::get_if<bool>(&property.second);
341ac6a4445SGunnar Mills         if (value == nullptr)
342ac6a4445SGunnar Mills         {
343ac6a4445SGunnar Mills             messages::internalError(aResp->res);
344601af5edSChicago Duan             return;
345ac6a4445SGunnar Mills         }
346d7f04fd9SNan Zhou         aResp->res.jsonValue[jsonPtr]["IsRankSpareEnabled"] = *value;
347ac6a4445SGunnar Mills     }
348ac6a4445SGunnar Mills     else if (property.first == "MaxAveragePowerLimitmW")
349ac6a4445SGunnar Mills     {
350ac6a4445SGunnar Mills         const auto* value =
351ac6a4445SGunnar Mills             std::get_if<std::vector<uint32_t>>(&property.second);
352ac6a4445SGunnar Mills         if (value == nullptr)
353ac6a4445SGunnar Mills         {
354ac6a4445SGunnar Mills             messages::internalError(aResp->res);
3550fda0f12SGeorge Liu             BMCWEB_LOG_DEBUG
3560fda0f12SGeorge Liu                 << "Invalid property type for MaxAveragePowerLimitmW";
357601af5edSChicago Duan             return;
358ac6a4445SGunnar Mills         }
359d7f04fd9SNan Zhou         aResp->res.jsonValue[jsonPtr]["MaxTDPMilliWatts"] = *value;
360ac6a4445SGunnar Mills     }
361ac6a4445SGunnar Mills     else if (property.first == "ConfigurationLocked")
362ac6a4445SGunnar Mills     {
363ac6a4445SGunnar Mills         const bool* value = std::get_if<bool>(&property.second);
364ac6a4445SGunnar Mills         if (value == nullptr)
365ac6a4445SGunnar Mills         {
366ac6a4445SGunnar Mills             messages::internalError(aResp->res);
367601af5edSChicago Duan             return;
368ac6a4445SGunnar Mills         }
369d7f04fd9SNan Zhou         aResp->res.jsonValue[jsonPtr]["ConfigurationLocked"] = *value;
370ac6a4445SGunnar Mills     }
371ac6a4445SGunnar Mills     else if (property.first == "AllowedMemoryModes")
372ac6a4445SGunnar Mills     {
37380badf7cSJiaqing Zhao         const std::string* value = std::get_if<std::string>(&property.second);
374ac6a4445SGunnar Mills         if (value == nullptr)
375ac6a4445SGunnar Mills         {
376ac6a4445SGunnar Mills             messages::internalError(aResp->res);
377ac6a4445SGunnar Mills             BMCWEB_LOG_DEBUG << "Invalid property type for FormFactor";
378601af5edSChicago Duan             return;
379ac6a4445SGunnar Mills         }
38080badf7cSJiaqing Zhao         constexpr const std::array<const char*, 3> values{"Volatile", "PMEM",
38180badf7cSJiaqing Zhao                                                           "Block"};
382ac6a4445SGunnar Mills 
383ac6a4445SGunnar Mills         for (const char* v : values)
384ac6a4445SGunnar Mills         {
385ac6a4445SGunnar Mills             if (boost::ends_with(*value, v))
386ac6a4445SGunnar Mills             {
387d7f04fd9SNan Zhou                 aResp->res.jsonValue[jsonPtr]["OperatingMemoryModes"].push_back(
388d7f04fd9SNan Zhou                     v);
389ac6a4445SGunnar Mills                 break;
390ac6a4445SGunnar Mills             }
391ac6a4445SGunnar Mills         }
392ac6a4445SGunnar Mills     }
393ac6a4445SGunnar Mills     else if (property.first == "MemoryMedia")
394ac6a4445SGunnar Mills     {
39580badf7cSJiaqing Zhao         const std::string* value = std::get_if<std::string>(&property.second);
396ac6a4445SGunnar Mills         if (value == nullptr)
397ac6a4445SGunnar Mills         {
398ac6a4445SGunnar Mills             messages::internalError(aResp->res);
399ac6a4445SGunnar Mills             BMCWEB_LOG_DEBUG << "Invalid property type for MemoryMedia";
400601af5edSChicago Duan             return;
401ac6a4445SGunnar Mills         }
402ac6a4445SGunnar Mills         constexpr const std::array<const char*, 3> values{"DRAM", "NAND",
403ac6a4445SGunnar Mills                                                           "Intel3DXPoint"};
404ac6a4445SGunnar Mills 
405ac6a4445SGunnar Mills         for (const char* v : values)
406ac6a4445SGunnar Mills         {
407ac6a4445SGunnar Mills             if (boost::ends_with(*value, v))
408ac6a4445SGunnar Mills             {
409d7f04fd9SNan Zhou                 aResp->res.jsonValue[jsonPtr]["MemoryMedia"].push_back(v);
410ac6a4445SGunnar Mills                 break;
411ac6a4445SGunnar Mills             }
412ac6a4445SGunnar Mills         }
413ac6a4445SGunnar Mills     }
414ac6a4445SGunnar Mills     // PersistantMemory.SecurityCapabilites interface
415ac6a4445SGunnar Mills     else if (property.first == "ConfigurationLockCapable" ||
416ac6a4445SGunnar Mills              property.first == "DataLockCapable" ||
417ac6a4445SGunnar Mills              property.first == "PassphraseCapable")
418ac6a4445SGunnar Mills     {
419ac6a4445SGunnar Mills         const bool* value = std::get_if<bool>(&property.second);
420ac6a4445SGunnar Mills         if (value == nullptr)
421ac6a4445SGunnar Mills         {
422ac6a4445SGunnar Mills             messages::internalError(aResp->res);
423601af5edSChicago Duan             return;
424ac6a4445SGunnar Mills         }
425d7f04fd9SNan Zhou         aResp->res.jsonValue[jsonPtr]["SecurityCapabilities"][property.first] =
426d7f04fd9SNan Zhou             *value;
427ac6a4445SGunnar Mills     }
428ac6a4445SGunnar Mills     else if (property.first == "MaxPassphraseCount" ||
429ac6a4445SGunnar Mills              property.first == "PassphraseLockLimit")
430ac6a4445SGunnar Mills     {
431ac6a4445SGunnar Mills         const uint64_t* value = std::get_if<uint64_t>(&property.second);
432ac6a4445SGunnar Mills         if (value == nullptr)
433ac6a4445SGunnar Mills         {
434ac6a4445SGunnar Mills             messages::internalError(aResp->res);
435601af5edSChicago Duan             return;
436ac6a4445SGunnar Mills         }
437d7f04fd9SNan Zhou         aResp->res.jsonValue[jsonPtr]["SecurityCapabilities"][property.first] =
438d7f04fd9SNan Zhou             *value;
439ac6a4445SGunnar Mills     }
440ac6a4445SGunnar Mills }
441ac6a4445SGunnar Mills 
4429a5aceacSNan Zhou inline void
4439a5aceacSNan Zhou     assembleDimmProperties(std::string_view dimmId,
4449a5aceacSNan Zhou                            const std::shared_ptr<bmcweb::AsyncResp>& aResp,
445d7f04fd9SNan Zhou                            const dbus::utility::DBusPropertiesMap& properties,
446d7f04fd9SNan Zhou                            const nlohmann::json::json_pointer& jsonPtr)
447ac6a4445SGunnar Mills {
448d7f04fd9SNan Zhou     aResp->res.jsonValue[jsonPtr]["Id"] = dimmId;
449d7f04fd9SNan Zhou     aResp->res.jsonValue[jsonPtr]["Name"] = "DIMM Slot";
450d7f04fd9SNan Zhou     aResp->res.jsonValue[jsonPtr]["Status"]["State"] = "Enabled";
451d7f04fd9SNan Zhou     aResp->res.jsonValue[jsonPtr]["Status"]["Health"] = "OK";
452ac6a4445SGunnar Mills 
453ac6a4445SGunnar Mills     for (const auto& property : properties)
454ac6a4445SGunnar Mills     {
455ac6a4445SGunnar Mills         if (property.first == "MemoryDataWidth")
456ac6a4445SGunnar Mills         {
4579a5aceacSNan Zhou             const uint16_t* value = std::get_if<uint16_t>(&property.second);
458ac6a4445SGunnar Mills             if (value == nullptr)
459ac6a4445SGunnar Mills             {
460ac6a4445SGunnar Mills                 continue;
461ac6a4445SGunnar Mills             }
462d7f04fd9SNan Zhou             aResp->res.jsonValue[jsonPtr]["DataWidthBits"] = *value;
463ac6a4445SGunnar Mills         }
464b9d36b47SEd Tanous         else if (property.first == "MemorySizeInKB")
465b9d36b47SEd Tanous         {
4669a5aceacSNan Zhou             const size_t* memorySize = std::get_if<size_t>(&property.second);
467b9d36b47SEd Tanous             if (memorySize == nullptr)
468b9d36b47SEd Tanous             {
469b9d36b47SEd Tanous                 // Important property not in desired type
470b9d36b47SEd Tanous                 messages::internalError(aResp->res);
471b9d36b47SEd Tanous                 return;
472b9d36b47SEd Tanous             }
473d7f04fd9SNan Zhou             aResp->res.jsonValue[jsonPtr]["CapacityMiB"] = (*memorySize >> 10);
474b9d36b47SEd Tanous         }
475ac6a4445SGunnar Mills         else if (property.first == "PartNumber")
476ac6a4445SGunnar Mills         {
477ac6a4445SGunnar Mills             const std::string* value =
478ac6a4445SGunnar Mills                 std::get_if<std::string>(&property.second);
479ac6a4445SGunnar Mills             if (value == nullptr)
480ac6a4445SGunnar Mills             {
481ac6a4445SGunnar Mills                 continue;
482ac6a4445SGunnar Mills             }
483d7f04fd9SNan Zhou             aResp->res.jsonValue[jsonPtr]["PartNumber"] = *value;
484ac6a4445SGunnar Mills         }
485ac6a4445SGunnar Mills         else if (property.first == "SerialNumber")
486ac6a4445SGunnar Mills         {
487ac6a4445SGunnar Mills             const std::string* value =
488ac6a4445SGunnar Mills                 std::get_if<std::string>(&property.second);
489ac6a4445SGunnar Mills             if (value == nullptr)
490ac6a4445SGunnar Mills             {
491ac6a4445SGunnar Mills                 continue;
492ac6a4445SGunnar Mills             }
493d7f04fd9SNan Zhou             aResp->res.jsonValue[jsonPtr]["SerialNumber"] = *value;
494ac6a4445SGunnar Mills         }
495ac6a4445SGunnar Mills         else if (property.first == "Manufacturer")
496ac6a4445SGunnar Mills         {
497ac6a4445SGunnar Mills             const std::string* value =
498ac6a4445SGunnar Mills                 std::get_if<std::string>(&property.second);
499ac6a4445SGunnar Mills             if (value == nullptr)
500ac6a4445SGunnar Mills             {
501ac6a4445SGunnar Mills                 continue;
502ac6a4445SGunnar Mills             }
503d7f04fd9SNan Zhou             aResp->res.jsonValue[jsonPtr]["Manufacturer"] = *value;
504ac6a4445SGunnar Mills         }
505ac6a4445SGunnar Mills         else if (property.first == "RevisionCode")
506ac6a4445SGunnar Mills         {
5079a5aceacSNan Zhou             const uint16_t* value = std::get_if<uint16_t>(&property.second);
508ac6a4445SGunnar Mills 
509ac6a4445SGunnar Mills             if (value == nullptr)
510ac6a4445SGunnar Mills             {
511ac6a4445SGunnar Mills                 messages::internalError(aResp->res);
5129a5aceacSNan Zhou                 BMCWEB_LOG_DEBUG << "Invalid property type for RevisionCode";
513601af5edSChicago Duan                 return;
514ac6a4445SGunnar Mills             }
515d7f04fd9SNan Zhou             aResp->res.jsonValue[jsonPtr]["FirmwareRevision"] =
516d7f04fd9SNan Zhou                 std::to_string(*value);
517ac6a4445SGunnar Mills         }
5189a128eb3SJoshi-Mansi         else if (property.first == "Present")
5199a128eb3SJoshi-Mansi         {
5209a128eb3SJoshi-Mansi             const bool* value = std::get_if<bool>(&property.second);
5219a128eb3SJoshi-Mansi             if (value == nullptr)
5229a128eb3SJoshi-Mansi             {
5239a128eb3SJoshi-Mansi                 messages::internalError(aResp->res);
5249a5aceacSNan Zhou                 BMCWEB_LOG_DEBUG << "Invalid property type for Dimm Presence";
5259a128eb3SJoshi-Mansi                 return;
5269a128eb3SJoshi-Mansi             }
527e05aec50SEd Tanous             if (!*value)
5289a128eb3SJoshi-Mansi             {
529d7f04fd9SNan Zhou                 aResp->res.jsonValue[jsonPtr]["Status"]["State"] = "Absent";
5309a128eb3SJoshi-Mansi             }
5319a128eb3SJoshi-Mansi         }
532ac6a4445SGunnar Mills         else if (property.first == "MemoryTotalWidth")
533ac6a4445SGunnar Mills         {
5349a5aceacSNan Zhou             const uint16_t* value = std::get_if<uint16_t>(&property.second);
535ac6a4445SGunnar Mills             if (value == nullptr)
536ac6a4445SGunnar Mills             {
537ac6a4445SGunnar Mills                 continue;
538ac6a4445SGunnar Mills             }
539d7f04fd9SNan Zhou             aResp->res.jsonValue[jsonPtr]["BusWidthBits"] = *value;
540ac6a4445SGunnar Mills         }
541ac6a4445SGunnar Mills         else if (property.first == "ECC")
542ac6a4445SGunnar Mills         {
543ac6a4445SGunnar Mills             const std::string* value =
544ac6a4445SGunnar Mills                 std::get_if<std::string>(&property.second);
545ac6a4445SGunnar Mills             if (value == nullptr)
546ac6a4445SGunnar Mills             {
547ac6a4445SGunnar Mills                 messages::internalError(aResp->res);
548ac6a4445SGunnar Mills                 BMCWEB_LOG_DEBUG << "Invalid property type for ECC";
549601af5edSChicago Duan                 return;
550ac6a4445SGunnar Mills             }
551ac6a4445SGunnar Mills             constexpr const std::array<const char*, 4> values{
5529a5aceacSNan Zhou                 "NoECC", "SingleBitECC", "MultiBitECC", "AddressParity"};
553ac6a4445SGunnar Mills 
554ac6a4445SGunnar Mills             for (const char* v : values)
555ac6a4445SGunnar Mills             {
556ac6a4445SGunnar Mills                 if (boost::ends_with(*value, v))
557ac6a4445SGunnar Mills                 {
558d7f04fd9SNan Zhou                     aResp->res.jsonValue[jsonPtr]["ErrorCorrection"] = v;
559ac6a4445SGunnar Mills                     break;
560ac6a4445SGunnar Mills                 }
561ac6a4445SGunnar Mills             }
562ac6a4445SGunnar Mills         }
563ac6a4445SGunnar Mills         else if (property.first == "FormFactor")
564ac6a4445SGunnar Mills         {
565ac6a4445SGunnar Mills             const std::string* value =
566ac6a4445SGunnar Mills                 std::get_if<std::string>(&property.second);
567ac6a4445SGunnar Mills             if (value == nullptr)
568ac6a4445SGunnar Mills             {
569ac6a4445SGunnar Mills                 messages::internalError(aResp->res);
5709a5aceacSNan Zhou                 BMCWEB_LOG_DEBUG << "Invalid property type for FormFactor";
571601af5edSChicago Duan                 return;
572ac6a4445SGunnar Mills             }
573ac6a4445SGunnar Mills             constexpr const std::array<const char*, 11> values{
5749a5aceacSNan Zhou                 "RDIMM",       "UDIMM",       "SO_DIMM",      "LRDIMM",
5759a5aceacSNan Zhou                 "Mini_RDIMM",  "Mini_UDIMM",  "SO_RDIMM_72b", "SO_UDIMM_72b",
5769a5aceacSNan Zhou                 "SO_DIMM_16b", "SO_DIMM_32b", "Die"};
577ac6a4445SGunnar Mills 
578ac6a4445SGunnar Mills             for (const char* v : values)
579ac6a4445SGunnar Mills             {
580ac6a4445SGunnar Mills                 if (boost::ends_with(*value, v))
581ac6a4445SGunnar Mills                 {
582d7f04fd9SNan Zhou                     aResp->res.jsonValue[jsonPtr]["BaseModuleType"] = v;
583ac6a4445SGunnar Mills                     break;
584ac6a4445SGunnar Mills                 }
585ac6a4445SGunnar Mills             }
586ac6a4445SGunnar Mills         }
587ac6a4445SGunnar Mills         else if (property.first == "AllowedSpeedsMT")
588ac6a4445SGunnar Mills         {
589ac6a4445SGunnar Mills             const std::vector<uint16_t>* value =
590ac6a4445SGunnar Mills                 std::get_if<std::vector<uint16_t>>(&property.second);
591ac6a4445SGunnar Mills             if (value == nullptr)
592ac6a4445SGunnar Mills             {
593ac6a4445SGunnar Mills                 continue;
594ac6a4445SGunnar Mills             }
595d7f04fd9SNan Zhou             nlohmann::json& jValue =
596d7f04fd9SNan Zhou                 aResp->res.jsonValue[jsonPtr]["AllowedSpeedsMHz"];
597ac6a4445SGunnar Mills             jValue = nlohmann::json::array();
598ac6a4445SGunnar Mills             for (uint16_t subVal : *value)
599ac6a4445SGunnar Mills             {
600ac6a4445SGunnar Mills                 jValue.push_back(subVal);
601ac6a4445SGunnar Mills             }
602ac6a4445SGunnar Mills         }
603ac6a4445SGunnar Mills         else if (property.first == "MemoryAttributes")
604ac6a4445SGunnar Mills         {
6059a5aceacSNan Zhou             const uint8_t* value = std::get_if<uint8_t>(&property.second);
606ac6a4445SGunnar Mills 
607ac6a4445SGunnar Mills             if (value == nullptr)
608ac6a4445SGunnar Mills             {
609ac6a4445SGunnar Mills                 messages::internalError(aResp->res);
610ac6a4445SGunnar Mills                 BMCWEB_LOG_DEBUG
611ac6a4445SGunnar Mills                     << "Invalid property type for MemoryAttributes";
612601af5edSChicago Duan                 return;
613ac6a4445SGunnar Mills             }
614d7f04fd9SNan Zhou             aResp->res.jsonValue[jsonPtr]["RankCount"] =
615d7f04fd9SNan Zhou                 static_cast<uint64_t>(*value);
616ac6a4445SGunnar Mills         }
617ac6a4445SGunnar Mills         else if (property.first == "MemoryConfiguredSpeedInMhz")
618ac6a4445SGunnar Mills         {
6199a5aceacSNan Zhou             const uint16_t* value = std::get_if<uint16_t>(&property.second);
620ac6a4445SGunnar Mills             if (value == nullptr)
621ac6a4445SGunnar Mills             {
622ac6a4445SGunnar Mills                 continue;
623ac6a4445SGunnar Mills             }
624d7f04fd9SNan Zhou             aResp->res.jsonValue[jsonPtr]["OperatingSpeedMhz"] = *value;
625ac6a4445SGunnar Mills         }
626ac6a4445SGunnar Mills         else if (property.first == "MemoryType")
627ac6a4445SGunnar Mills         {
6289a5aceacSNan Zhou             const auto* value = std::get_if<std::string>(&property.second);
629ac6a4445SGunnar Mills             if (value != nullptr)
630ac6a4445SGunnar Mills             {
631313efb1cSGunnar Mills                 std::string memoryDeviceType =
632313efb1cSGunnar Mills                     translateMemoryTypeToRedfish(*value);
633313efb1cSGunnar Mills                 // Values like "Unknown" or "Other" will return empty
634313efb1cSGunnar Mills                 // so just leave off
635313efb1cSGunnar Mills                 if (!memoryDeviceType.empty())
636ac6a4445SGunnar Mills                 {
637d7f04fd9SNan Zhou                     aResp->res.jsonValue[jsonPtr]["MemoryDeviceType"] =
638d7f04fd9SNan Zhou                         memoryDeviceType;
639ac6a4445SGunnar Mills                 }
640ac6a4445SGunnar Mills                 if (value->find("DDR") != std::string::npos)
641ac6a4445SGunnar Mills                 {
642d7f04fd9SNan Zhou                     aResp->res.jsonValue[jsonPtr]["MemoryType"] = "DRAM";
643ac6a4445SGunnar Mills                 }
644ac6a4445SGunnar Mills                 else if (boost::ends_with(*value, "Logical"))
645ac6a4445SGunnar Mills                 {
646d7f04fd9SNan Zhou                     aResp->res.jsonValue[jsonPtr]["MemoryType"] = "IntelOptane";
647ac6a4445SGunnar Mills                 }
648ac6a4445SGunnar Mills             }
649ac6a4445SGunnar Mills         }
650ac6a4445SGunnar Mills         // memory location interface
651ac6a4445SGunnar Mills         else if (property.first == "Channel" ||
652ac6a4445SGunnar Mills                  property.first == "MemoryController" ||
653ac6a4445SGunnar Mills                  property.first == "Slot" || property.first == "Socket")
654ac6a4445SGunnar Mills         {
655ac6a4445SGunnar Mills             const std::string* value =
656ac6a4445SGunnar Mills                 std::get_if<std::string>(&property.second);
657ac6a4445SGunnar Mills             if (value == nullptr)
658ac6a4445SGunnar Mills             {
659ac6a4445SGunnar Mills                 messages::internalError(aResp->res);
660601af5edSChicago Duan                 return;
661ac6a4445SGunnar Mills             }
662d7f04fd9SNan Zhou             aResp->res.jsonValue[jsonPtr]["MemoryLocation"][property.first] =
663d7f04fd9SNan Zhou                 *value;
664ac6a4445SGunnar Mills         }
665ee135e24SSunnySrivastava1984         else if (property.first == "SparePartNumber")
666ee135e24SSunnySrivastava1984         {
667ee135e24SSunnySrivastava1984             const std::string* value =
668ee135e24SSunnySrivastava1984                 std::get_if<std::string>(&property.second);
669ee135e24SSunnySrivastava1984             if (value == nullptr)
670ee135e24SSunnySrivastava1984             {
671ee135e24SSunnySrivastava1984                 messages::internalError(aResp->res);
672601af5edSChicago Duan                 return;
673ee135e24SSunnySrivastava1984             }
674d7f04fd9SNan Zhou             aResp->res.jsonValue[jsonPtr]["SparePartNumber"] = *value;
675ee135e24SSunnySrivastava1984         }
676ee135e24SSunnySrivastava1984         else if (property.first == "Model")
677ee135e24SSunnySrivastava1984         {
678ee135e24SSunnySrivastava1984             const std::string* value =
679ee135e24SSunnySrivastava1984                 std::get_if<std::string>(&property.second);
680ee135e24SSunnySrivastava1984             if (value == nullptr)
681ee135e24SSunnySrivastava1984             {
682ee135e24SSunnySrivastava1984                 messages::internalError(aResp->res);
683601af5edSChicago Duan                 return;
684ee135e24SSunnySrivastava1984             }
685d7f04fd9SNan Zhou             aResp->res.jsonValue[jsonPtr]["Model"] = *value;
686ee135e24SSunnySrivastava1984         }
687ee135e24SSunnySrivastava1984         else if (property.first == "LocationCode")
688ee135e24SSunnySrivastava1984         {
689ee135e24SSunnySrivastava1984             const std::string* value =
690ee135e24SSunnySrivastava1984                 std::get_if<std::string>(&property.second);
691ee135e24SSunnySrivastava1984             if (value == nullptr)
692ee135e24SSunnySrivastava1984             {
693ee135e24SSunnySrivastava1984                 messages::internalError(aResp->res);
694601af5edSChicago Duan                 return;
695ee135e24SSunnySrivastava1984             }
696d7f04fd9SNan Zhou             aResp->res.jsonValue[jsonPtr]["Location"]["PartLocation"]
697d7f04fd9SNan Zhou                                 ["ServiceLabel"] = *value;
698ee135e24SSunnySrivastava1984         }
699ac6a4445SGunnar Mills         else
700ac6a4445SGunnar Mills         {
701d7f04fd9SNan Zhou             getPersistentMemoryProperties(aResp, property, jsonPtr);
702ac6a4445SGunnar Mills         }
703ac6a4445SGunnar Mills     }
7049a5aceacSNan Zhou }
7059a5aceacSNan Zhou 
7069a5aceacSNan Zhou inline void getDimmDataByService(std::shared_ptr<bmcweb::AsyncResp> aResp,
7079a5aceacSNan Zhou                                  const std::string& dimmId,
7089a5aceacSNan Zhou                                  const std::string& service,
7099a5aceacSNan Zhou                                  const std::string& objPath)
7109a5aceacSNan Zhou {
7119a5aceacSNan Zhou     auto health = std::make_shared<HealthPopulate>(aResp);
7129a5aceacSNan Zhou     health->selfPath = objPath;
7139a5aceacSNan Zhou     health->populate();
7149a5aceacSNan Zhou 
7159a5aceacSNan Zhou     BMCWEB_LOG_DEBUG << "Get available system components.";
7169a5aceacSNan Zhou     crow::connections::systemBus->async_method_call(
7179a5aceacSNan Zhou         [dimmId, aResp{std::move(aResp)}](
7189a5aceacSNan Zhou             const boost::system::error_code ec,
7199a5aceacSNan Zhou             const dbus::utility::DBusPropertiesMap& properties) {
7209a5aceacSNan Zhou         if (ec)
7219a5aceacSNan Zhou         {
7229a5aceacSNan Zhou             BMCWEB_LOG_DEBUG << "DBUS response error";
7239a5aceacSNan Zhou             messages::internalError(aResp->res);
7249a5aceacSNan Zhou             return;
7259a5aceacSNan Zhou         }
726d7f04fd9SNan Zhou         assembleDimmProperties(dimmId, aResp, properties, ""_json_pointer);
727ac6a4445SGunnar Mills         },
728ac6a4445SGunnar Mills         service, objPath, "org.freedesktop.DBus.Properties", "GetAll", "");
729ac6a4445SGunnar Mills }
730ac6a4445SGunnar Mills 
731ef00d7d4SNan Zhou inline void assembleDimmPartitionData(
732ef00d7d4SNan Zhou     const std::shared_ptr<bmcweb::AsyncResp>& aResp,
733d7f04fd9SNan Zhou     const dbus::utility::DBusPropertiesMap& properties,
734d7f04fd9SNan Zhou     const nlohmann::json::json_pointer& regionPtr)
735ac6a4445SGunnar Mills {
736d7f04fd9SNan Zhou     nlohmann::json::object_t partition;
737ac6a4445SGunnar Mills     for (const auto& [key, val] : properties)
738ac6a4445SGunnar Mills     {
739ac6a4445SGunnar Mills         if (key == "MemoryClassification")
740ac6a4445SGunnar Mills         {
741ac6a4445SGunnar Mills             const std::string* value = std::get_if<std::string>(&val);
742ac6a4445SGunnar Mills             if (value == nullptr)
743ac6a4445SGunnar Mills             {
744ac6a4445SGunnar Mills                 messages::internalError(aResp->res);
745601af5edSChicago Duan                 return;
746ac6a4445SGunnar Mills             }
747ac6a4445SGunnar Mills             partition[key] = *value;
748ac6a4445SGunnar Mills         }
749ac6a4445SGunnar Mills         else if (key == "OffsetInKiB")
750ac6a4445SGunnar Mills         {
751ac6a4445SGunnar Mills             const uint64_t* value = std::get_if<uint64_t>(&val);
752ac6a4445SGunnar Mills             if (value == nullptr)
753ac6a4445SGunnar Mills             {
754ac6a4445SGunnar Mills                 messages::internalError(aResp->res);
755601af5edSChicago Duan                 return;
756ac6a4445SGunnar Mills             }
757ac6a4445SGunnar Mills 
758ac6a4445SGunnar Mills             partition["OffsetMiB"] = (*value >> 10);
759ac6a4445SGunnar Mills         }
760ac6a4445SGunnar Mills         else if (key == "PartitionId")
761ac6a4445SGunnar Mills         {
762ac6a4445SGunnar Mills             const std::string* value = std::get_if<std::string>(&val);
763ac6a4445SGunnar Mills             if (value == nullptr)
764ac6a4445SGunnar Mills             {
765ac6a4445SGunnar Mills                 messages::internalError(aResp->res);
766601af5edSChicago Duan                 return;
767ac6a4445SGunnar Mills             }
768ac6a4445SGunnar Mills             partition["RegionId"] = *value;
769ac6a4445SGunnar Mills         }
770ac6a4445SGunnar Mills 
771ac6a4445SGunnar Mills         else if (key == "PassphraseState")
772ac6a4445SGunnar Mills         {
773ac6a4445SGunnar Mills             const bool* value = std::get_if<bool>(&val);
774ac6a4445SGunnar Mills             if (value == nullptr)
775ac6a4445SGunnar Mills             {
776ac6a4445SGunnar Mills                 messages::internalError(aResp->res);
777601af5edSChicago Duan                 return;
778ac6a4445SGunnar Mills             }
779ac6a4445SGunnar Mills             partition["PassphraseEnabled"] = *value;
780ac6a4445SGunnar Mills         }
781ac6a4445SGunnar Mills         else if (key == "SizeInKiB")
782ac6a4445SGunnar Mills         {
783ac6a4445SGunnar Mills             const uint64_t* value = std::get_if<uint64_t>(&val);
784ac6a4445SGunnar Mills             if (value == nullptr)
785ac6a4445SGunnar Mills             {
786ac6a4445SGunnar Mills                 messages::internalError(aResp->res);
787ef00d7d4SNan Zhou                 BMCWEB_LOG_DEBUG << "Invalid property type for SizeInKiB";
788601af5edSChicago Duan                 return;
789ac6a4445SGunnar Mills             }
790ac6a4445SGunnar Mills             partition["SizeMiB"] = (*value >> 10);
791ac6a4445SGunnar Mills         }
792ac6a4445SGunnar Mills     }
793d7f04fd9SNan Zhou     aResp->res.jsonValue[regionPtr].emplace_back(std::move(partition));
794ef00d7d4SNan Zhou }
795ef00d7d4SNan Zhou 
796ef00d7d4SNan Zhou inline void getDimmPartitionData(std::shared_ptr<bmcweb::AsyncResp> aResp,
797ef00d7d4SNan Zhou                                  const std::string& service,
798ef00d7d4SNan Zhou                                  const std::string& path)
799ef00d7d4SNan Zhou {
800ef00d7d4SNan Zhou     crow::connections::systemBus->async_method_call(
801ef00d7d4SNan Zhou         [aResp{std::move(aResp)}](
802ef00d7d4SNan Zhou             const boost::system::error_code ec,
803ef00d7d4SNan Zhou             const dbus::utility::DBusPropertiesMap& properties) {
804ef00d7d4SNan Zhou         if (ec)
805ef00d7d4SNan Zhou         {
806ef00d7d4SNan Zhou             BMCWEB_LOG_DEBUG << "DBUS response error";
807ef00d7d4SNan Zhou             messages::internalError(aResp->res);
808ef00d7d4SNan Zhou 
809ef00d7d4SNan Zhou             return;
810ef00d7d4SNan Zhou         }
811d7f04fd9SNan Zhou         nlohmann::json::json_pointer regionPtr = "/Regions"_json_pointer;
812d7f04fd9SNan Zhou         assembleDimmPartitionData(aResp, properties, regionPtr);
813ac6a4445SGunnar Mills         },
814ac6a4445SGunnar Mills 
815ac6a4445SGunnar Mills         service, path, "org.freedesktop.DBus.Properties", "GetAll",
816ac6a4445SGunnar Mills         "xyz.openbmc_project.Inventory.Item.PersistentMemory.Partition");
817ac6a4445SGunnar Mills }
818ac6a4445SGunnar Mills 
8198d1b46d7Szhanghch05 inline void getDimmData(std::shared_ptr<bmcweb::AsyncResp> aResp,
820ac6a4445SGunnar Mills                         const std::string& dimmId)
821ac6a4445SGunnar Mills {
822ac6a4445SGunnar Mills     BMCWEB_LOG_DEBUG << "Get available system dimm resources.";
823ac6a4445SGunnar Mills     crow::connections::systemBus->async_method_call(
824ac6a4445SGunnar Mills         [dimmId, aResp{std::move(aResp)}](
825ac6a4445SGunnar Mills             const boost::system::error_code ec,
826b9d36b47SEd Tanous             const dbus::utility::MapperGetSubTreeResponse& subtree) {
827ac6a4445SGunnar Mills         if (ec)
828ac6a4445SGunnar Mills         {
829ac6a4445SGunnar Mills             BMCWEB_LOG_DEBUG << "DBUS response error";
830ac6a4445SGunnar Mills             messages::internalError(aResp->res);
831ac6a4445SGunnar Mills 
832ac6a4445SGunnar Mills             return;
833ac6a4445SGunnar Mills         }
834ac6a4445SGunnar Mills         bool found = false;
835*76686dccSNan Zhou         for (const auto& [rawPath, object] : subtree)
836ac6a4445SGunnar Mills         {
837*76686dccSNan Zhou             sdbusplus::message::object_path path(rawPath);
838ac6a4445SGunnar Mills             for (const auto& [service, interfaces] : object)
839ac6a4445SGunnar Mills             {
840b9d36b47SEd Tanous                 for (const auto& interface : interfaces)
841ac6a4445SGunnar Mills                 {
842b9d36b47SEd Tanous                     if (interface ==
843*76686dccSNan Zhou                             "xyz.openbmc_project.Inventory.Item.Dimm" &&
844*76686dccSNan Zhou                         path.filename() == dimmId)
845b9d36b47SEd Tanous                     {
846*76686dccSNan Zhou                         getDimmDataByService(aResp, dimmId, service, rawPath);
847ac6a4445SGunnar Mills                         found = true;
848ac6a4445SGunnar Mills                     }
849ac6a4445SGunnar Mills 
850b9d36b47SEd Tanous                     // partitions are separate as there can be multiple
851b9d36b47SEd Tanous                     // per
852ac6a4445SGunnar Mills                     // device, i.e.
853ac6a4445SGunnar Mills                     // /xyz/openbmc_project/Inventory/Item/Dimm1/Partition1
854ac6a4445SGunnar Mills                     // /xyz/openbmc_project/Inventory/Item/Dimm1/Partition2
855b9d36b47SEd Tanous                     if (interface ==
856*76686dccSNan Zhou                             "xyz.openbmc_project.Inventory.Item.PersistentMemory.Partition" &&
857*76686dccSNan Zhou                         path.parent_path().filename() == dimmId)
858ac6a4445SGunnar Mills                     {
859*76686dccSNan Zhou                         getDimmPartitionData(aResp, service, rawPath);
860ac6a4445SGunnar Mills                     }
861ac6a4445SGunnar Mills                 }
862ac6a4445SGunnar Mills             }
863b9d36b47SEd Tanous         }
864ac6a4445SGunnar Mills         // Object not found
865ac6a4445SGunnar Mills         if (!found)
866ac6a4445SGunnar Mills         {
867ac6a4445SGunnar Mills             messages::resourceNotFound(aResp->res, "Memory", dimmId);
8681a1d5d6dSNan Zhou             return;
869ac6a4445SGunnar Mills         }
8701a1d5d6dSNan Zhou         // Set @odata only if object is found
8711a1d5d6dSNan Zhou         aResp->res.jsonValue["@odata.type"] = "#Memory.v1_11_0.Memory";
8721a1d5d6dSNan Zhou         aResp->res.jsonValue["@odata.id"] =
8731a1d5d6dSNan Zhou             "/redfish/v1/Systems/system/Memory/" + dimmId;
874ac6a4445SGunnar Mills         return;
875ac6a4445SGunnar Mills         },
876ac6a4445SGunnar Mills         "xyz.openbmc_project.ObjectMapper",
877ac6a4445SGunnar Mills         "/xyz/openbmc_project/object_mapper",
878ac6a4445SGunnar Mills         "xyz.openbmc_project.ObjectMapper", "GetSubTree",
879ac6a4445SGunnar Mills         "/xyz/openbmc_project/inventory", 0,
880ac6a4445SGunnar Mills         std::array<const char*, 2>{
881ac6a4445SGunnar Mills             "xyz.openbmc_project.Inventory.Item.Dimm",
882ac6a4445SGunnar Mills             "xyz.openbmc_project.Inventory.Item.PersistentMemory.Partition"});
883ac6a4445SGunnar Mills }
884ac6a4445SGunnar Mills 
8857e860f15SJohn Edward Broadbent inline void requestRoutesMemoryCollection(App& app)
886ac6a4445SGunnar Mills {
887ac6a4445SGunnar Mills     /**
888ac6a4445SGunnar Mills      * Functions triggers appropriate requests on DBus
889ac6a4445SGunnar Mills      */
8907e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/Memory/")
891ed398213SEd Tanous         .privileges(redfish::privileges::getMemoryCollection)
8927e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::get)(
89345ca1b86SEd Tanous             [&app](const crow::Request& req,
8947e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
8953ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
89645ca1b86SEd Tanous         {
89745ca1b86SEd Tanous             return;
89845ca1b86SEd Tanous         }
8998d1b46d7Szhanghch05         asyncResp->res.jsonValue["@odata.type"] =
9008d1b46d7Szhanghch05             "#MemoryCollection.MemoryCollection";
9018d1b46d7Szhanghch05         asyncResp->res.jsonValue["Name"] = "Memory Module Collection";
9028d1b46d7Szhanghch05         asyncResp->res.jsonValue["@odata.id"] =
9038d1b46d7Szhanghch05             "/redfish/v1/Systems/system/Memory";
904ac6a4445SGunnar Mills 
90505030b8eSGunnar Mills         collection_util::getCollectionMembers(
90605030b8eSGunnar Mills             asyncResp, "/redfish/v1/Systems/system/Memory",
90705030b8eSGunnar Mills             {"xyz.openbmc_project.Inventory.Item.Dimm"});
9087e860f15SJohn Edward Broadbent         });
909ac6a4445SGunnar Mills }
910ac6a4445SGunnar Mills 
9117e860f15SJohn Edward Broadbent inline void requestRoutesMemory(App& app)
9127e860f15SJohn Edward Broadbent {
913ac6a4445SGunnar Mills     /**
914ac6a4445SGunnar Mills      * Functions triggers appropriate requests on DBus
915ac6a4445SGunnar Mills      */
9167e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/Memory/<str>/")
917ed398213SEd Tanous         .privileges(redfish::privileges::getMemory)
9187e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::get)(
91945ca1b86SEd Tanous             [&app](const crow::Request& req,
9207e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
9217e860f15SJohn Edward Broadbent                    const std::string& dimmId) {
9223ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
92345ca1b86SEd Tanous         {
92445ca1b86SEd Tanous             return;
92545ca1b86SEd Tanous         }
926ac6a4445SGunnar Mills         getDimmData(asyncResp, dimmId);
9277e860f15SJohn Edward Broadbent         });
928ac6a4445SGunnar Mills }
929ac6a4445SGunnar Mills 
930ac6a4445SGunnar Mills } // namespace redfish
931