xref: /openbmc/bmcweb/features/redfish/lib/memory.hpp (revision b9d36b4791d77a47e1f3c5c4564fcdf7cc68c115)
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>
21168e20c1SEd Tanous #include <dbus_utility.hpp>
22ed398213SEd Tanous #include <registries/privilege_registry.hpp>
23ac6a4445SGunnar Mills #include <utils/collection.hpp>
24f201ffb4SEd Tanous #include <utils/hex_utils.hpp>
25ac6a4445SGunnar Mills #include <utils/json_utils.hpp>
26ac6a4445SGunnar Mills 
27ac6a4445SGunnar Mills namespace redfish
28ac6a4445SGunnar Mills {
29ac6a4445SGunnar Mills 
30313efb1cSGunnar Mills inline std::string translateMemoryTypeToRedfish(const std::string& memoryType)
31313efb1cSGunnar Mills {
32313efb1cSGunnar Mills     if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR")
33313efb1cSGunnar Mills     {
34313efb1cSGunnar Mills         return "DDR";
35313efb1cSGunnar Mills     }
36313efb1cSGunnar Mills     if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR2")
37313efb1cSGunnar Mills     {
38313efb1cSGunnar Mills         return "DDR2";
39313efb1cSGunnar Mills     }
40313efb1cSGunnar Mills     if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR3")
41313efb1cSGunnar Mills     {
42313efb1cSGunnar Mills         return "DDR3";
43313efb1cSGunnar Mills     }
44313efb1cSGunnar Mills     if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR4")
45313efb1cSGunnar Mills     {
46313efb1cSGunnar Mills         return "DDR4";
47313efb1cSGunnar Mills     }
48313efb1cSGunnar Mills     if (memoryType ==
49313efb1cSGunnar Mills         "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR4E_SDRAM")
50313efb1cSGunnar Mills     {
51313efb1cSGunnar Mills         return "DDR4E_SDRAM";
52313efb1cSGunnar Mills     }
5311a2f0f0SMansi Joshi     if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR5")
5411a2f0f0SMansi Joshi     {
5511a2f0f0SMansi Joshi         return "DDR5";
5611a2f0f0SMansi Joshi     }
57313efb1cSGunnar Mills     if (memoryType ==
58313efb1cSGunnar Mills         "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.LPDDR4_SDRAM")
59313efb1cSGunnar Mills     {
60313efb1cSGunnar Mills         return "LPDDR4_SDRAM";
61313efb1cSGunnar Mills     }
62313efb1cSGunnar Mills     if (memoryType ==
63313efb1cSGunnar Mills         "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.LPDDR3_SDRAM")
64313efb1cSGunnar Mills     {
65313efb1cSGunnar Mills         return "LPDDR3_SDRAM";
66313efb1cSGunnar Mills     }
67313efb1cSGunnar Mills     if (memoryType ==
68313efb1cSGunnar Mills         "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR2_SDRAM_FB_DIMM")
69313efb1cSGunnar Mills     {
70313efb1cSGunnar Mills         return "DDR2_SDRAM_FB_DIMM";
71313efb1cSGunnar Mills     }
720fda0f12SGeorge Liu     if (memoryType ==
730fda0f12SGeorge Liu         "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR2_SDRAM_FB_DIMM_PROB")
74313efb1cSGunnar Mills     {
75313efb1cSGunnar Mills         return "DDR2_SDRAM_FB_DIMM_PROBE";
76313efb1cSGunnar Mills     }
77313efb1cSGunnar Mills     if (memoryType ==
78313efb1cSGunnar Mills         "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR_SGRAM")
79313efb1cSGunnar Mills     {
80313efb1cSGunnar Mills         return "DDR_SGRAM";
81313efb1cSGunnar Mills     }
82313efb1cSGunnar Mills     if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.ROM")
83313efb1cSGunnar Mills     {
84313efb1cSGunnar Mills         return "ROM";
85313efb1cSGunnar Mills     }
86313efb1cSGunnar Mills     if (memoryType ==
87313efb1cSGunnar Mills         "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.SDRAM")
88313efb1cSGunnar Mills     {
89313efb1cSGunnar Mills         return "SDRAM";
90313efb1cSGunnar Mills     }
91313efb1cSGunnar Mills     if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.EDO")
92313efb1cSGunnar Mills     {
93313efb1cSGunnar Mills         return "EDO";
94313efb1cSGunnar Mills     }
95313efb1cSGunnar Mills     if (memoryType ==
96313efb1cSGunnar Mills         "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.FastPageMode")
97313efb1cSGunnar Mills     {
98313efb1cSGunnar Mills         return "FastPageMode";
99313efb1cSGunnar Mills     }
100313efb1cSGunnar Mills     if (memoryType ==
101313efb1cSGunnar Mills         "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.PipelinedNibble")
102313efb1cSGunnar Mills     {
103313efb1cSGunnar Mills         return "PipelinedNibble";
104313efb1cSGunnar Mills     }
105313efb1cSGunnar Mills     if (memoryType ==
106313efb1cSGunnar Mills         "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.Logical")
107313efb1cSGunnar Mills     {
108313efb1cSGunnar Mills         return "Logical";
109313efb1cSGunnar Mills     }
110313efb1cSGunnar Mills     if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.HBM")
111313efb1cSGunnar Mills     {
112313efb1cSGunnar Mills         return "HBM";
113313efb1cSGunnar Mills     }
114313efb1cSGunnar Mills     if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.HBM2")
115313efb1cSGunnar Mills     {
116313efb1cSGunnar Mills         return "HBM2";
117313efb1cSGunnar Mills     }
118313efb1cSGunnar Mills     // This is values like Other or Unknown
119313efb1cSGunnar Mills     // Also D-Bus values:
120313efb1cSGunnar Mills     // DRAM
121313efb1cSGunnar Mills     // EDRAM
122313efb1cSGunnar Mills     // VRAM
123313efb1cSGunnar Mills     // SRAM
124313efb1cSGunnar Mills     // RAM
125313efb1cSGunnar Mills     // FLASH
126313efb1cSGunnar Mills     // EEPROM
127313efb1cSGunnar Mills     // FEPROM
128313efb1cSGunnar Mills     // EPROM
129313efb1cSGunnar Mills     // CDRAM
130313efb1cSGunnar Mills     // ThreeDRAM
131313efb1cSGunnar Mills     // RDRAM
132313efb1cSGunnar Mills     // FBD2
133313efb1cSGunnar Mills     // LPDDR_SDRAM
134313efb1cSGunnar Mills     // LPDDR2_SDRAM
13511a2f0f0SMansi Joshi     // LPDDR5_SDRAM
136313efb1cSGunnar Mills     return "";
137313efb1cSGunnar Mills }
138313efb1cSGunnar Mills 
139168e20c1SEd Tanous inline void dimmPropToHex(
140168e20c1SEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& aResp, const char* key,
141168e20c1SEd Tanous     const std::pair<std::string, dbus::utility::DbusVariantType>& property)
142ac6a4445SGunnar Mills {
143ac6a4445SGunnar Mills     const uint16_t* value = std::get_if<uint16_t>(&property.second);
144ac6a4445SGunnar Mills     if (value == nullptr)
145ac6a4445SGunnar Mills     {
146ac6a4445SGunnar Mills         messages::internalError(aResp->res);
147ac6a4445SGunnar Mills         BMCWEB_LOG_DEBUG << "Invalid property type for " << property.first;
148ac6a4445SGunnar Mills         return;
149ac6a4445SGunnar Mills     }
150ac6a4445SGunnar Mills 
151866e4862SEd Tanous     aResp->res.jsonValue[key] = "0x" + intToHexString(*value, 4);
152ac6a4445SGunnar Mills }
153ac6a4445SGunnar Mills 
1548d1b46d7Szhanghch05 inline void getPersistentMemoryProperties(
1558d1b46d7Szhanghch05     const std::shared_ptr<bmcweb::AsyncResp>& aResp,
15680badf7cSJiaqing Zhao     const std::pair<std::string, dbus::utility::DbusVariantType>& property)
157ac6a4445SGunnar Mills {
158ac6a4445SGunnar Mills     if (property.first == "ModuleManufacturerID")
159ac6a4445SGunnar Mills     {
160ac6a4445SGunnar Mills         dimmPropToHex(aResp, "ModuleManufacturerID", property);
161ac6a4445SGunnar Mills     }
162ac6a4445SGunnar Mills     else if (property.first == "ModuleProductID")
163ac6a4445SGunnar Mills     {
164ac6a4445SGunnar Mills         dimmPropToHex(aResp, "ModuleProductID", property);
165ac6a4445SGunnar Mills     }
166ac6a4445SGunnar Mills     else if (property.first == "SubsystemVendorID")
167ac6a4445SGunnar Mills     {
168ac6a4445SGunnar Mills         dimmPropToHex(aResp, "MemorySubsystemControllerManufacturerID",
169ac6a4445SGunnar Mills                       property);
170ac6a4445SGunnar Mills     }
171ac6a4445SGunnar Mills     else if (property.first == "SubsystemDeviceID")
172ac6a4445SGunnar Mills     {
17380badf7cSJiaqing Zhao         dimmPropToHex(aResp, "MemorySubsystemControllerProductID", property);
174ac6a4445SGunnar Mills     }
175ac6a4445SGunnar Mills     else if (property.first == "VolatileRegionSizeLimitInKiB")
176ac6a4445SGunnar Mills     {
177ac6a4445SGunnar Mills         const uint64_t* value = std::get_if<uint64_t>(&property.second);
178ac6a4445SGunnar Mills 
179ac6a4445SGunnar Mills         if (value == nullptr)
180ac6a4445SGunnar Mills         {
181ac6a4445SGunnar Mills             messages::internalError(aResp->res);
1820fda0f12SGeorge Liu             BMCWEB_LOG_DEBUG
1830fda0f12SGeorge Liu                 << "Invalid property type for VolatileRegionSizeLimitKiB";
184601af5edSChicago Duan             return;
185ac6a4445SGunnar Mills         }
186ac6a4445SGunnar Mills         aResp->res.jsonValue["VolatileRegionSizeLimitMiB"] = (*value) >> 10;
187ac6a4445SGunnar Mills     }
188ac6a4445SGunnar Mills     else if (property.first == "PmRegionSizeLimitInKiB")
189ac6a4445SGunnar Mills     {
190ac6a4445SGunnar Mills         const uint64_t* value = std::get_if<uint64_t>(&property.second);
191ac6a4445SGunnar Mills 
192ac6a4445SGunnar Mills         if (value == nullptr)
193ac6a4445SGunnar Mills         {
194ac6a4445SGunnar Mills             messages::internalError(aResp->res);
19580badf7cSJiaqing Zhao             BMCWEB_LOG_DEBUG << "Invalid property type for PmRegioSizeLimitKiB";
196601af5edSChicago Duan             return;
197ac6a4445SGunnar Mills         }
19880badf7cSJiaqing Zhao         aResp->res.jsonValue["PersistentRegionSizeLimitMiB"] = (*value) >> 10;
199ac6a4445SGunnar Mills     }
200ac6a4445SGunnar Mills     else if (property.first == "VolatileSizeInKiB")
201ac6a4445SGunnar Mills     {
202ac6a4445SGunnar Mills         const uint64_t* value = std::get_if<uint64_t>(&property.second);
203ac6a4445SGunnar Mills 
204ac6a4445SGunnar Mills         if (value == nullptr)
205ac6a4445SGunnar Mills         {
206ac6a4445SGunnar Mills             messages::internalError(aResp->res);
20780badf7cSJiaqing Zhao             BMCWEB_LOG_DEBUG << "Invalid property type for VolatileSizeInKiB";
208601af5edSChicago Duan             return;
209ac6a4445SGunnar Mills         }
210ac6a4445SGunnar Mills         aResp->res.jsonValue["VolatileSizeMiB"] = (*value) >> 10;
211ac6a4445SGunnar Mills     }
212ac6a4445SGunnar Mills     else if (property.first == "PmSizeInKiB")
213ac6a4445SGunnar Mills     {
214ac6a4445SGunnar Mills         const uint64_t* value = std::get_if<uint64_t>(&property.second);
215ac6a4445SGunnar Mills         if (value == nullptr)
216ac6a4445SGunnar Mills         {
217ac6a4445SGunnar Mills             messages::internalError(aResp->res);
218ac6a4445SGunnar Mills             BMCWEB_LOG_DEBUG << "Invalid property type for PmSizeInKiB";
219601af5edSChicago Duan             return;
220ac6a4445SGunnar Mills         }
221ac6a4445SGunnar Mills         aResp->res.jsonValue["NonVolatileSizeMiB"] = (*value) >> 10;
222ac6a4445SGunnar Mills     }
223ac6a4445SGunnar Mills     else if (property.first == "CacheSizeInKB")
224ac6a4445SGunnar Mills     {
225ac6a4445SGunnar Mills         const uint64_t* value = std::get_if<uint64_t>(&property.second);
226ac6a4445SGunnar Mills         if (value == nullptr)
227ac6a4445SGunnar Mills         {
228ac6a4445SGunnar Mills             messages::internalError(aResp->res);
229ac6a4445SGunnar Mills             BMCWEB_LOG_DEBUG << "Invalid property type for CacheSizeInKB";
230601af5edSChicago Duan             return;
231ac6a4445SGunnar Mills         }
232ac6a4445SGunnar Mills         aResp->res.jsonValue["CacheSizeMiB"] = (*value >> 10);
233ac6a4445SGunnar Mills     }
234ac6a4445SGunnar Mills 
235ac6a4445SGunnar Mills     else if (property.first == "VoltaileRegionMaxSizeInKib")
236ac6a4445SGunnar Mills     {
237ac6a4445SGunnar Mills         const uint64_t* value = std::get_if<uint64_t>(&property.second);
238ac6a4445SGunnar Mills 
239ac6a4445SGunnar Mills         if (value == nullptr)
240ac6a4445SGunnar Mills         {
241ac6a4445SGunnar Mills             messages::internalError(aResp->res);
2420fda0f12SGeorge Liu             BMCWEB_LOG_DEBUG
2430fda0f12SGeorge Liu                 << "Invalid property type for VolatileRegionMaxSizeInKib";
244601af5edSChicago Duan             return;
245ac6a4445SGunnar Mills         }
246ac6a4445SGunnar Mills         aResp->res.jsonValue["VolatileRegionSizeMaxMiB"] = (*value) >> 10;
247ac6a4445SGunnar Mills     }
248ac6a4445SGunnar Mills     else if (property.first == "PmRegionMaxSizeInKiB")
249ac6a4445SGunnar Mills     {
250ac6a4445SGunnar Mills         const uint64_t* value = std::get_if<uint64_t>(&property.second);
251ac6a4445SGunnar Mills 
252ac6a4445SGunnar Mills         if (value == nullptr)
253ac6a4445SGunnar Mills         {
254ac6a4445SGunnar Mills             messages::internalError(aResp->res);
255ac6a4445SGunnar Mills             BMCWEB_LOG_DEBUG
256ac6a4445SGunnar Mills                 << "Invalid property type for PmRegionMaxSizeInKiB";
257601af5edSChicago Duan             return;
258ac6a4445SGunnar Mills         }
259ac6a4445SGunnar Mills         aResp->res.jsonValue["PersistentRegionSizeMaxMiB"] = (*value) >> 10;
260ac6a4445SGunnar Mills     }
261ac6a4445SGunnar Mills     else if (property.first == "AllocationIncrementInKiB")
262ac6a4445SGunnar Mills     {
263ac6a4445SGunnar Mills         const uint64_t* value = std::get_if<uint64_t>(&property.second);
264ac6a4445SGunnar Mills 
265ac6a4445SGunnar Mills         if (value == nullptr)
266ac6a4445SGunnar Mills         {
267ac6a4445SGunnar Mills             messages::internalError(aResp->res);
2680fda0f12SGeorge Liu             BMCWEB_LOG_DEBUG
2690fda0f12SGeorge Liu                 << "Invalid property type for AllocationIncrementInKiB";
270601af5edSChicago Duan             return;
271ac6a4445SGunnar Mills         }
272ac6a4445SGunnar Mills         aResp->res.jsonValue["AllocationIncrementMiB"] = (*value) >> 10;
273ac6a4445SGunnar Mills     }
274ac6a4445SGunnar Mills     else if (property.first == "AllocationAlignmentInKiB")
275ac6a4445SGunnar Mills     {
276ac6a4445SGunnar Mills         const uint64_t* value = std::get_if<uint64_t>(&property.second);
277ac6a4445SGunnar Mills 
278ac6a4445SGunnar Mills         if (value == nullptr)
279ac6a4445SGunnar Mills         {
280ac6a4445SGunnar Mills             messages::internalError(aResp->res);
2810fda0f12SGeorge Liu             BMCWEB_LOG_DEBUG
2820fda0f12SGeorge Liu                 << "Invalid property type for AllocationAlignmentInKiB";
283601af5edSChicago Duan             return;
284ac6a4445SGunnar Mills         }
285ac6a4445SGunnar Mills         aResp->res.jsonValue["AllocationAlignmentMiB"] = (*value) >> 10;
286ac6a4445SGunnar Mills     }
287ac6a4445SGunnar Mills     else if (property.first == "VolatileRegionNumberLimit")
288ac6a4445SGunnar Mills     {
289ac6a4445SGunnar Mills         const uint64_t* value = std::get_if<uint64_t>(&property.second);
290ac6a4445SGunnar Mills         if (value == nullptr)
291ac6a4445SGunnar Mills         {
292ac6a4445SGunnar Mills             messages::internalError(aResp->res);
293601af5edSChicago Duan             return;
294ac6a4445SGunnar Mills         }
295ac6a4445SGunnar Mills         aResp->res.jsonValue["VolatileRegionNumberLimit"] = *value;
296ac6a4445SGunnar Mills     }
297ac6a4445SGunnar Mills     else if (property.first == "PmRegionNumberLimit")
298ac6a4445SGunnar Mills     {
299ac6a4445SGunnar Mills         const uint64_t* value = std::get_if<uint64_t>(&property.second);
300ac6a4445SGunnar Mills         if (value == nullptr)
301ac6a4445SGunnar Mills         {
302ac6a4445SGunnar Mills             messages::internalError(aResp->res);
303601af5edSChicago Duan             return;
304ac6a4445SGunnar Mills         }
305ac6a4445SGunnar Mills         aResp->res.jsonValue["PersistentRegionNumberLimit"] = *value;
306ac6a4445SGunnar Mills     }
307ac6a4445SGunnar Mills     else if (property.first == "SpareDeviceCount")
308ac6a4445SGunnar Mills     {
309ac6a4445SGunnar Mills         const uint64_t* value = std::get_if<uint64_t>(&property.second);
310ac6a4445SGunnar Mills         if (value == nullptr)
311ac6a4445SGunnar Mills         {
312ac6a4445SGunnar Mills             messages::internalError(aResp->res);
313601af5edSChicago Duan             return;
314ac6a4445SGunnar Mills         }
315ac6a4445SGunnar Mills         aResp->res.jsonValue["SpareDeviceCount"] = *value;
316ac6a4445SGunnar Mills     }
317ac6a4445SGunnar Mills     else if (property.first == "IsSpareDeviceInUse")
318ac6a4445SGunnar Mills     {
319ac6a4445SGunnar Mills         const bool* value = std::get_if<bool>(&property.second);
320ac6a4445SGunnar Mills         if (value == nullptr)
321ac6a4445SGunnar Mills         {
322ac6a4445SGunnar Mills             messages::internalError(aResp->res);
323601af5edSChicago Duan             return;
324ac6a4445SGunnar Mills         }
325ac6a4445SGunnar Mills         aResp->res.jsonValue["IsSpareDeviceEnabled"] = *value;
326ac6a4445SGunnar Mills     }
327ac6a4445SGunnar Mills     else if (property.first == "IsRankSpareEnabled")
328ac6a4445SGunnar Mills     {
329ac6a4445SGunnar Mills         const bool* value = std::get_if<bool>(&property.second);
330ac6a4445SGunnar Mills         if (value == nullptr)
331ac6a4445SGunnar Mills         {
332ac6a4445SGunnar Mills             messages::internalError(aResp->res);
333601af5edSChicago Duan             return;
334ac6a4445SGunnar Mills         }
335ac6a4445SGunnar Mills         aResp->res.jsonValue["IsRankSpareEnabled"] = *value;
336ac6a4445SGunnar Mills     }
337ac6a4445SGunnar Mills     else if (property.first == "MaxAveragePowerLimitmW")
338ac6a4445SGunnar Mills     {
339ac6a4445SGunnar Mills         const auto* value =
340ac6a4445SGunnar Mills             std::get_if<std::vector<uint32_t>>(&property.second);
341ac6a4445SGunnar Mills         if (value == nullptr)
342ac6a4445SGunnar Mills         {
343ac6a4445SGunnar Mills             messages::internalError(aResp->res);
3440fda0f12SGeorge Liu             BMCWEB_LOG_DEBUG
3450fda0f12SGeorge Liu                 << "Invalid property type for MaxAveragePowerLimitmW";
346601af5edSChicago Duan             return;
347ac6a4445SGunnar Mills         }
348ac6a4445SGunnar Mills         aResp->res.jsonValue["MaxTDPMilliWatts"] = *value;
349ac6a4445SGunnar Mills     }
350ac6a4445SGunnar Mills     else if (property.first == "ConfigurationLocked")
351ac6a4445SGunnar Mills     {
352ac6a4445SGunnar Mills         const bool* value = std::get_if<bool>(&property.second);
353ac6a4445SGunnar Mills         if (value == nullptr)
354ac6a4445SGunnar Mills         {
355ac6a4445SGunnar Mills             messages::internalError(aResp->res);
356601af5edSChicago Duan             return;
357ac6a4445SGunnar Mills         }
358ac6a4445SGunnar Mills         aResp->res.jsonValue["ConfigurationLocked"] = *value;
359ac6a4445SGunnar Mills     }
360ac6a4445SGunnar Mills     else if (property.first == "AllowedMemoryModes")
361ac6a4445SGunnar Mills     {
36280badf7cSJiaqing Zhao         const std::string* value = std::get_if<std::string>(&property.second);
363ac6a4445SGunnar Mills         if (value == nullptr)
364ac6a4445SGunnar Mills         {
365ac6a4445SGunnar Mills             messages::internalError(aResp->res);
366ac6a4445SGunnar Mills             BMCWEB_LOG_DEBUG << "Invalid property type for FormFactor";
367601af5edSChicago Duan             return;
368ac6a4445SGunnar Mills         }
36980badf7cSJiaqing Zhao         constexpr const std::array<const char*, 3> values{"Volatile", "PMEM",
37080badf7cSJiaqing Zhao                                                           "Block"};
371ac6a4445SGunnar Mills 
372ac6a4445SGunnar Mills         for (const char* v : values)
373ac6a4445SGunnar Mills         {
374ac6a4445SGunnar Mills             if (boost::ends_with(*value, v))
375ac6a4445SGunnar Mills             {
376ac6a4445SGunnar Mills                 aResp->res.jsonValue["OperatingMemoryModes "] = v;
377ac6a4445SGunnar Mills                 break;
378ac6a4445SGunnar Mills             }
379ac6a4445SGunnar Mills         }
380ac6a4445SGunnar Mills     }
381ac6a4445SGunnar Mills     else if (property.first == "MemoryMedia")
382ac6a4445SGunnar Mills     {
38380badf7cSJiaqing Zhao         const std::string* value = std::get_if<std::string>(&property.second);
384ac6a4445SGunnar Mills         if (value == nullptr)
385ac6a4445SGunnar Mills         {
386ac6a4445SGunnar Mills             messages::internalError(aResp->res);
387ac6a4445SGunnar Mills             BMCWEB_LOG_DEBUG << "Invalid property type for MemoryMedia";
388601af5edSChicago Duan             return;
389ac6a4445SGunnar Mills         }
390ac6a4445SGunnar Mills         constexpr const std::array<const char*, 3> values{"DRAM", "NAND",
391ac6a4445SGunnar Mills                                                           "Intel3DXPoint"};
392ac6a4445SGunnar Mills 
393ac6a4445SGunnar Mills         for (const char* v : values)
394ac6a4445SGunnar Mills         {
395ac6a4445SGunnar Mills             if (boost::ends_with(*value, v))
396ac6a4445SGunnar Mills             {
397ac6a4445SGunnar Mills                 aResp->res.jsonValue["MemoryMedia"] = v;
398ac6a4445SGunnar Mills                 break;
399ac6a4445SGunnar Mills             }
400ac6a4445SGunnar Mills         }
401ac6a4445SGunnar Mills     }
402ac6a4445SGunnar Mills     // PersistantMemory.SecurityCapabilites interface
403ac6a4445SGunnar Mills     else if (property.first == "ConfigurationLockCapable" ||
404ac6a4445SGunnar Mills              property.first == "DataLockCapable" ||
405ac6a4445SGunnar Mills              property.first == "PassphraseCapable")
406ac6a4445SGunnar Mills     {
407ac6a4445SGunnar Mills         const bool* value = std::get_if<bool>(&property.second);
408ac6a4445SGunnar Mills         if (value == nullptr)
409ac6a4445SGunnar Mills         {
410ac6a4445SGunnar Mills             messages::internalError(aResp->res);
411601af5edSChicago Duan             return;
412ac6a4445SGunnar Mills         }
41380badf7cSJiaqing Zhao         aResp->res.jsonValue["SecurityCapabilities"][property.first] = *value;
414ac6a4445SGunnar Mills     }
415ac6a4445SGunnar Mills     else if (property.first == "MaxPassphraseCount" ||
416ac6a4445SGunnar Mills              property.first == "PassphraseLockLimit")
417ac6a4445SGunnar Mills     {
418ac6a4445SGunnar Mills         const uint64_t* value = std::get_if<uint64_t>(&property.second);
419ac6a4445SGunnar Mills         if (value == nullptr)
420ac6a4445SGunnar Mills         {
421ac6a4445SGunnar Mills             messages::internalError(aResp->res);
422601af5edSChicago Duan             return;
423ac6a4445SGunnar Mills         }
42480badf7cSJiaqing Zhao         aResp->res.jsonValue["SecurityCapabilities"][property.first] = *value;
425ac6a4445SGunnar Mills     }
426ac6a4445SGunnar Mills }
427ac6a4445SGunnar Mills 
4288d1b46d7Szhanghch05 inline void getDimmDataByService(std::shared_ptr<bmcweb::AsyncResp> aResp,
429ac6a4445SGunnar Mills                                  const std::string& dimmId,
430ac6a4445SGunnar Mills                                  const std::string& service,
431ac6a4445SGunnar Mills                                  const std::string& objPath)
432ac6a4445SGunnar Mills {
433ac6a4445SGunnar Mills     auto health = std::make_shared<HealthPopulate>(aResp);
434ac6a4445SGunnar Mills     health->selfPath = objPath;
435ac6a4445SGunnar Mills     health->populate();
436ac6a4445SGunnar Mills 
437ac6a4445SGunnar Mills     BMCWEB_LOG_DEBUG << "Get available system components.";
438ac6a4445SGunnar Mills     crow::connections::systemBus->async_method_call(
439*b9d36b47SEd Tanous         [dimmId, aResp{std::move(aResp)}](
440*b9d36b47SEd Tanous             const boost::system::error_code ec,
441*b9d36b47SEd Tanous             const dbus::utility::DBusPropertiesMap& properties) {
442ac6a4445SGunnar Mills             if (ec)
443ac6a4445SGunnar Mills             {
444ac6a4445SGunnar Mills                 BMCWEB_LOG_DEBUG << "DBUS response error";
445ac6a4445SGunnar Mills                 messages::internalError(aResp->res);
446ac6a4445SGunnar Mills                 return;
447ac6a4445SGunnar Mills             }
448ac6a4445SGunnar Mills             aResp->res.jsonValue["Id"] = dimmId;
449ac6a4445SGunnar Mills             aResp->res.jsonValue["Name"] = "DIMM Slot";
450ac6a4445SGunnar Mills             aResp->res.jsonValue["Status"]["State"] = "Enabled";
451ac6a4445SGunnar Mills             aResp->res.jsonValue["Status"]["Health"] = "OK";
452ac6a4445SGunnar Mills 
453ac6a4445SGunnar Mills             for (const auto& property : properties)
454ac6a4445SGunnar Mills             {
455ac6a4445SGunnar Mills                 if (property.first == "MemoryDataWidth")
456ac6a4445SGunnar Mills                 {
457ac6a4445SGunnar Mills                     const uint16_t* value =
458ac6a4445SGunnar Mills                         std::get_if<uint16_t>(&property.second);
459ac6a4445SGunnar Mills                     if (value == nullptr)
460ac6a4445SGunnar Mills                     {
461ac6a4445SGunnar Mills                         continue;
462ac6a4445SGunnar Mills                     }
463ac6a4445SGunnar Mills                     aResp->res.jsonValue["DataWidthBits"] = *value;
464ac6a4445SGunnar Mills                 }
465*b9d36b47SEd Tanous                 else if (property.first == "MemorySizeInKB")
466*b9d36b47SEd Tanous                 {
467*b9d36b47SEd Tanous                     const uint32_t* memorySize =
468*b9d36b47SEd Tanous                         std::get_if<uint32_t>(&property.second);
469*b9d36b47SEd Tanous                     if (memorySize == nullptr)
470*b9d36b47SEd Tanous                     {
471*b9d36b47SEd Tanous                         // Important property not in desired type
472*b9d36b47SEd Tanous                         messages::internalError(aResp->res);
473*b9d36b47SEd Tanous                         return;
474*b9d36b47SEd Tanous                     }
475*b9d36b47SEd Tanous                     aResp->res.jsonValue["CapacityMiB"] = (*memorySize >> 10);
476*b9d36b47SEd Tanous                 }
477ac6a4445SGunnar Mills                 else if (property.first == "PartNumber")
478ac6a4445SGunnar Mills                 {
479ac6a4445SGunnar Mills                     const std::string* value =
480ac6a4445SGunnar Mills                         std::get_if<std::string>(&property.second);
481ac6a4445SGunnar Mills                     if (value == nullptr)
482ac6a4445SGunnar Mills                     {
483ac6a4445SGunnar Mills                         continue;
484ac6a4445SGunnar Mills                     }
485ac6a4445SGunnar Mills                     aResp->res.jsonValue["PartNumber"] = *value;
486ac6a4445SGunnar Mills                 }
487ac6a4445SGunnar Mills                 else if (property.first == "SerialNumber")
488ac6a4445SGunnar Mills                 {
489ac6a4445SGunnar Mills                     const std::string* value =
490ac6a4445SGunnar Mills                         std::get_if<std::string>(&property.second);
491ac6a4445SGunnar Mills                     if (value == nullptr)
492ac6a4445SGunnar Mills                     {
493ac6a4445SGunnar Mills                         continue;
494ac6a4445SGunnar Mills                     }
495ac6a4445SGunnar Mills                     aResp->res.jsonValue["SerialNumber"] = *value;
496ac6a4445SGunnar Mills                 }
497ac6a4445SGunnar Mills                 else if (property.first == "Manufacturer")
498ac6a4445SGunnar Mills                 {
499ac6a4445SGunnar Mills                     const std::string* value =
500ac6a4445SGunnar Mills                         std::get_if<std::string>(&property.second);
501ac6a4445SGunnar Mills                     if (value == nullptr)
502ac6a4445SGunnar Mills                     {
503ac6a4445SGunnar Mills                         continue;
504ac6a4445SGunnar Mills                     }
505ac6a4445SGunnar Mills                     aResp->res.jsonValue["Manufacturer"] = *value;
506ac6a4445SGunnar Mills                 }
507ac6a4445SGunnar Mills                 else if (property.first == "RevisionCode")
508ac6a4445SGunnar Mills                 {
509ac6a4445SGunnar Mills                     const uint16_t* value =
510ac6a4445SGunnar Mills                         std::get_if<uint16_t>(&property.second);
511ac6a4445SGunnar Mills 
512ac6a4445SGunnar Mills                     if (value == nullptr)
513ac6a4445SGunnar Mills                     {
514ac6a4445SGunnar Mills                         messages::internalError(aResp->res);
515ac6a4445SGunnar Mills                         BMCWEB_LOG_DEBUG
516ac6a4445SGunnar Mills                             << "Invalid property type for RevisionCode";
517601af5edSChicago Duan                         return;
518ac6a4445SGunnar Mills                     }
519ac6a4445SGunnar Mills                     aResp->res.jsonValue["FirmwareRevision"] =
520ac6a4445SGunnar Mills                         std::to_string(*value);
521ac6a4445SGunnar Mills                 }
5229a128eb3SJoshi-Mansi                 else if (property.first == "Present")
5239a128eb3SJoshi-Mansi                 {
5249a128eb3SJoshi-Mansi                     const bool* value = std::get_if<bool>(&property.second);
5259a128eb3SJoshi-Mansi                     if (value == nullptr)
5269a128eb3SJoshi-Mansi                     {
5279a128eb3SJoshi-Mansi                         messages::internalError(aResp->res);
5289a128eb3SJoshi-Mansi                         BMCWEB_LOG_DEBUG
5299a128eb3SJoshi-Mansi                             << "Invalid property type for Dimm Presence";
5309a128eb3SJoshi-Mansi                         return;
5319a128eb3SJoshi-Mansi                     }
532e05aec50SEd Tanous                     if (!*value)
5339a128eb3SJoshi-Mansi                     {
5349a128eb3SJoshi-Mansi                         aResp->res.jsonValue["Status"]["State"] = "Absent";
5359a128eb3SJoshi-Mansi                     }
5369a128eb3SJoshi-Mansi                 }
537ac6a4445SGunnar Mills                 else if (property.first == "MemoryTotalWidth")
538ac6a4445SGunnar Mills                 {
539ac6a4445SGunnar Mills                     const uint16_t* value =
540ac6a4445SGunnar Mills                         std::get_if<uint16_t>(&property.second);
541ac6a4445SGunnar Mills                     if (value == nullptr)
542ac6a4445SGunnar Mills                     {
543ac6a4445SGunnar Mills                         continue;
544ac6a4445SGunnar Mills                     }
545ac6a4445SGunnar Mills                     aResp->res.jsonValue["BusWidthBits"] = *value;
546ac6a4445SGunnar Mills                 }
547ac6a4445SGunnar Mills                 else if (property.first == "ECC")
548ac6a4445SGunnar Mills                 {
549ac6a4445SGunnar Mills                     const std::string* value =
550ac6a4445SGunnar Mills                         std::get_if<std::string>(&property.second);
551ac6a4445SGunnar Mills                     if (value == nullptr)
552ac6a4445SGunnar Mills                     {
553ac6a4445SGunnar Mills                         messages::internalError(aResp->res);
554ac6a4445SGunnar Mills                         BMCWEB_LOG_DEBUG << "Invalid property type for ECC";
555601af5edSChicago Duan                         return;
556ac6a4445SGunnar Mills                     }
557ac6a4445SGunnar Mills                     constexpr const std::array<const char*, 4> values{
558ac6a4445SGunnar Mills                         "NoECC", "SingleBitECC", "MultiBitECC",
559ac6a4445SGunnar Mills                         "AddressParity"};
560ac6a4445SGunnar Mills 
561ac6a4445SGunnar Mills                     for (const char* v : values)
562ac6a4445SGunnar Mills                     {
563ac6a4445SGunnar Mills                         if (boost::ends_with(*value, v))
564ac6a4445SGunnar Mills                         {
565ac6a4445SGunnar Mills                             aResp->res.jsonValue["ErrorCorrection"] = v;
566ac6a4445SGunnar Mills                             break;
567ac6a4445SGunnar Mills                         }
568ac6a4445SGunnar Mills                     }
569ac6a4445SGunnar Mills                 }
570ac6a4445SGunnar Mills                 else if (property.first == "FormFactor")
571ac6a4445SGunnar Mills                 {
572ac6a4445SGunnar Mills                     const std::string* value =
573ac6a4445SGunnar Mills                         std::get_if<std::string>(&property.second);
574ac6a4445SGunnar Mills                     if (value == nullptr)
575ac6a4445SGunnar Mills                     {
576ac6a4445SGunnar Mills                         messages::internalError(aResp->res);
577ac6a4445SGunnar Mills                         BMCWEB_LOG_DEBUG
578ac6a4445SGunnar Mills                             << "Invalid property type for FormFactor";
579601af5edSChicago Duan                         return;
580ac6a4445SGunnar Mills                     }
581ac6a4445SGunnar Mills                     constexpr const std::array<const char*, 11> values{
582ac6a4445SGunnar Mills                         "RDIMM",        "UDIMM",        "SO_DIMM",
583ac6a4445SGunnar Mills                         "LRDIMM",       "Mini_RDIMM",   "Mini_UDIMM",
584ac6a4445SGunnar Mills                         "SO_RDIMM_72b", "SO_UDIMM_72b", "SO_DIMM_16b",
585ac6a4445SGunnar Mills                         "SO_DIMM_32b",  "Die"};
586ac6a4445SGunnar Mills 
587ac6a4445SGunnar Mills                     for (const char* v : values)
588ac6a4445SGunnar Mills                     {
589ac6a4445SGunnar Mills                         if (boost::ends_with(*value, v))
590ac6a4445SGunnar Mills                         {
591ac6a4445SGunnar Mills                             aResp->res.jsonValue["BaseModuleType"] = v;
592ac6a4445SGunnar Mills                             break;
593ac6a4445SGunnar Mills                         }
594ac6a4445SGunnar Mills                     }
595ac6a4445SGunnar Mills                 }
596ac6a4445SGunnar Mills                 else if (property.first == "AllowedSpeedsMT")
597ac6a4445SGunnar Mills                 {
598ac6a4445SGunnar Mills                     const std::vector<uint16_t>* value =
599ac6a4445SGunnar Mills                         std::get_if<std::vector<uint16_t>>(&property.second);
600ac6a4445SGunnar Mills                     if (value == nullptr)
601ac6a4445SGunnar Mills                     {
602ac6a4445SGunnar Mills                         continue;
603ac6a4445SGunnar Mills                     }
604ac6a4445SGunnar Mills                     nlohmann::json& jValue =
605ac6a4445SGunnar Mills                         aResp->res.jsonValue["AllowedSpeedsMHz"];
606ac6a4445SGunnar Mills                     jValue = nlohmann::json::array();
607ac6a4445SGunnar Mills                     for (uint16_t subVal : *value)
608ac6a4445SGunnar Mills                     {
609ac6a4445SGunnar Mills                         jValue.push_back(subVal);
610ac6a4445SGunnar Mills                     }
611ac6a4445SGunnar Mills                 }
612ac6a4445SGunnar Mills                 else if (property.first == "MemoryAttributes")
613ac6a4445SGunnar Mills                 {
614ac6a4445SGunnar Mills                     const uint8_t* value =
615ac6a4445SGunnar Mills                         std::get_if<uint8_t>(&property.second);
616ac6a4445SGunnar Mills 
617ac6a4445SGunnar Mills                     if (value == nullptr)
618ac6a4445SGunnar Mills                     {
619ac6a4445SGunnar Mills                         messages::internalError(aResp->res);
620ac6a4445SGunnar Mills                         BMCWEB_LOG_DEBUG
621ac6a4445SGunnar Mills                             << "Invalid property type for MemoryAttributes";
622601af5edSChicago Duan                         return;
623ac6a4445SGunnar Mills                     }
624ac6a4445SGunnar Mills                     aResp->res.jsonValue["RankCount"] =
625ac6a4445SGunnar Mills                         static_cast<uint64_t>(*value);
626ac6a4445SGunnar Mills                 }
627ac6a4445SGunnar Mills                 else if (property.first == "MemoryConfiguredSpeedInMhz")
628ac6a4445SGunnar Mills                 {
629ac6a4445SGunnar Mills                     const uint16_t* value =
630ac6a4445SGunnar Mills                         std::get_if<uint16_t>(&property.second);
631ac6a4445SGunnar Mills                     if (value == nullptr)
632ac6a4445SGunnar Mills                     {
633ac6a4445SGunnar Mills                         continue;
634ac6a4445SGunnar Mills                     }
635ac6a4445SGunnar Mills                     aResp->res.jsonValue["OperatingSpeedMhz"] = *value;
636ac6a4445SGunnar Mills                 }
637ac6a4445SGunnar Mills                 else if (property.first == "MemoryType")
638ac6a4445SGunnar Mills                 {
639ac6a4445SGunnar Mills                     const auto* value =
640ac6a4445SGunnar Mills                         std::get_if<std::string>(&property.second);
641ac6a4445SGunnar Mills                     if (value != nullptr)
642ac6a4445SGunnar Mills                     {
643313efb1cSGunnar Mills                         std::string memoryDeviceType =
644313efb1cSGunnar Mills                             translateMemoryTypeToRedfish(*value);
645313efb1cSGunnar Mills                         // Values like "Unknown" or "Other" will return empty
646313efb1cSGunnar Mills                         // so just leave off
647313efb1cSGunnar Mills                         if (!memoryDeviceType.empty())
648ac6a4445SGunnar Mills                         {
649313efb1cSGunnar Mills                             aResp->res.jsonValue["MemoryDeviceType"] =
650313efb1cSGunnar Mills                                 memoryDeviceType;
651ac6a4445SGunnar Mills                         }
652ac6a4445SGunnar Mills                         if (value->find("DDR") != std::string::npos)
653ac6a4445SGunnar Mills                         {
654ac6a4445SGunnar Mills                             aResp->res.jsonValue["MemoryType"] = "DRAM";
655ac6a4445SGunnar Mills                         }
656ac6a4445SGunnar Mills                         else if (boost::ends_with(*value, "Logical"))
657ac6a4445SGunnar Mills                         {
658ac6a4445SGunnar Mills                             aResp->res.jsonValue["MemoryType"] = "IntelOptane";
659ac6a4445SGunnar Mills                         }
660ac6a4445SGunnar Mills                     }
661ac6a4445SGunnar Mills                 }
662ac6a4445SGunnar Mills                 // memory location interface
663ac6a4445SGunnar Mills                 else if (property.first == "Channel" ||
664ac6a4445SGunnar Mills                          property.first == "MemoryController" ||
665ac6a4445SGunnar Mills                          property.first == "Slot" || property.first == "Socket")
666ac6a4445SGunnar Mills                 {
667ac6a4445SGunnar Mills                     const std::string* value =
668ac6a4445SGunnar Mills                         std::get_if<std::string>(&property.second);
669ac6a4445SGunnar Mills                     if (value == nullptr)
670ac6a4445SGunnar Mills                     {
671ac6a4445SGunnar Mills                         messages::internalError(aResp->res);
672601af5edSChicago Duan                         return;
673ac6a4445SGunnar Mills                     }
674ac6a4445SGunnar Mills                     aResp->res.jsonValue["MemoryLocation"][property.first] =
675ac6a4445SGunnar Mills                         *value;
676ac6a4445SGunnar Mills                 }
677ee135e24SSunnySrivastava1984                 else if (property.first == "SparePartNumber")
678ee135e24SSunnySrivastava1984                 {
679ee135e24SSunnySrivastava1984                     const std::string* value =
680ee135e24SSunnySrivastava1984                         std::get_if<std::string>(&property.second);
681ee135e24SSunnySrivastava1984                     if (value == nullptr)
682ee135e24SSunnySrivastava1984                     {
683ee135e24SSunnySrivastava1984                         messages::internalError(aResp->res);
684601af5edSChicago Duan                         return;
685ee135e24SSunnySrivastava1984                     }
686ee135e24SSunnySrivastava1984                     aResp->res.jsonValue["SparePartNumber"] = *value;
687ee135e24SSunnySrivastava1984                 }
688ee135e24SSunnySrivastava1984                 else if (property.first == "Model")
689ee135e24SSunnySrivastava1984                 {
690ee135e24SSunnySrivastava1984                     const std::string* value =
691ee135e24SSunnySrivastava1984                         std::get_if<std::string>(&property.second);
692ee135e24SSunnySrivastava1984                     if (value == nullptr)
693ee135e24SSunnySrivastava1984                     {
694ee135e24SSunnySrivastava1984                         messages::internalError(aResp->res);
695601af5edSChicago Duan                         return;
696ee135e24SSunnySrivastava1984                     }
697ee135e24SSunnySrivastava1984                     aResp->res.jsonValue["Model"] = *value;
698ee135e24SSunnySrivastava1984                 }
699ee135e24SSunnySrivastava1984                 else if (property.first == "LocationCode")
700ee135e24SSunnySrivastava1984                 {
701ee135e24SSunnySrivastava1984                     const std::string* value =
702ee135e24SSunnySrivastava1984                         std::get_if<std::string>(&property.second);
703ee135e24SSunnySrivastava1984                     if (value == nullptr)
704ee135e24SSunnySrivastava1984                     {
705ee135e24SSunnySrivastava1984                         messages::internalError(aResp->res);
706601af5edSChicago Duan                         return;
707ee135e24SSunnySrivastava1984                     }
708ee135e24SSunnySrivastava1984                     aResp->res
709ee135e24SSunnySrivastava1984                         .jsonValue["Location"]["PartLocation"]["ServiceLabel"] =
710ee135e24SSunnySrivastava1984                         *value;
711ee135e24SSunnySrivastava1984                 }
712ac6a4445SGunnar Mills                 else
713ac6a4445SGunnar Mills                 {
71480badf7cSJiaqing Zhao                     getPersistentMemoryProperties(aResp, property);
715ac6a4445SGunnar Mills                 }
716ac6a4445SGunnar Mills             }
717ac6a4445SGunnar Mills         },
718ac6a4445SGunnar Mills         service, objPath, "org.freedesktop.DBus.Properties", "GetAll", "");
719ac6a4445SGunnar Mills }
720ac6a4445SGunnar Mills 
7218d1b46d7Szhanghch05 inline void getDimmPartitionData(std::shared_ptr<bmcweb::AsyncResp> aResp,
722ac6a4445SGunnar Mills                                  const std::string& service,
723ac6a4445SGunnar Mills                                  const std::string& path)
724ac6a4445SGunnar Mills {
725ac6a4445SGunnar Mills     crow::connections::systemBus->async_method_call(
726ac6a4445SGunnar Mills         [aResp{std::move(aResp)}](
727ac6a4445SGunnar Mills             const boost::system::error_code ec,
728*b9d36b47SEd Tanous             const dbus::utility::DBusPropertiesMap& properties) {
729ac6a4445SGunnar Mills             if (ec)
730ac6a4445SGunnar Mills             {
731ac6a4445SGunnar Mills                 BMCWEB_LOG_DEBUG << "DBUS response error";
732ac6a4445SGunnar Mills                 messages::internalError(aResp->res);
733ac6a4445SGunnar Mills 
734ac6a4445SGunnar Mills                 return;
735ac6a4445SGunnar Mills             }
736ac6a4445SGunnar Mills 
737ac6a4445SGunnar Mills             nlohmann::json& partition =
738ac6a4445SGunnar Mills                 aResp->res.jsonValue["Regions"].emplace_back(
739ac6a4445SGunnar Mills                     nlohmann::json::object());
740ac6a4445SGunnar Mills             for (const auto& [key, val] : properties)
741ac6a4445SGunnar Mills             {
742ac6a4445SGunnar Mills                 if (key == "MemoryClassification")
743ac6a4445SGunnar Mills                 {
744ac6a4445SGunnar Mills                     const std::string* value = std::get_if<std::string>(&val);
745ac6a4445SGunnar Mills                     if (value == nullptr)
746ac6a4445SGunnar Mills                     {
747ac6a4445SGunnar Mills                         messages::internalError(aResp->res);
748601af5edSChicago Duan                         return;
749ac6a4445SGunnar Mills                     }
750ac6a4445SGunnar Mills                     partition[key] = *value;
751ac6a4445SGunnar Mills                 }
752ac6a4445SGunnar Mills                 else if (key == "OffsetInKiB")
753ac6a4445SGunnar Mills                 {
754ac6a4445SGunnar Mills                     const uint64_t* value = std::get_if<uint64_t>(&val);
755ac6a4445SGunnar Mills                     if (value == nullptr)
756ac6a4445SGunnar Mills                     {
757ac6a4445SGunnar Mills                         messages::internalError(aResp->res);
758601af5edSChicago Duan                         return;
759ac6a4445SGunnar Mills                     }
760ac6a4445SGunnar Mills 
761ac6a4445SGunnar Mills                     partition["OffsetMiB"] = (*value >> 10);
762ac6a4445SGunnar Mills                 }
763ac6a4445SGunnar Mills                 else if (key == "PartitionId")
764ac6a4445SGunnar Mills                 {
765ac6a4445SGunnar Mills                     const std::string* value = std::get_if<std::string>(&val);
766ac6a4445SGunnar Mills                     if (value == nullptr)
767ac6a4445SGunnar Mills                     {
768ac6a4445SGunnar Mills                         messages::internalError(aResp->res);
769601af5edSChicago Duan                         return;
770ac6a4445SGunnar Mills                     }
771ac6a4445SGunnar Mills                     partition["RegionId"] = *value;
772ac6a4445SGunnar Mills                 }
773ac6a4445SGunnar Mills 
774ac6a4445SGunnar Mills                 else if (key == "PassphraseState")
775ac6a4445SGunnar Mills                 {
776ac6a4445SGunnar Mills                     const bool* value = std::get_if<bool>(&val);
777ac6a4445SGunnar Mills                     if (value == nullptr)
778ac6a4445SGunnar Mills                     {
779ac6a4445SGunnar Mills                         messages::internalError(aResp->res);
780601af5edSChicago Duan                         return;
781ac6a4445SGunnar Mills                     }
782ac6a4445SGunnar Mills                     partition["PassphraseEnabled"] = *value;
783ac6a4445SGunnar Mills                 }
784ac6a4445SGunnar Mills                 else if (key == "SizeInKiB")
785ac6a4445SGunnar Mills                 {
786ac6a4445SGunnar Mills                     const uint64_t* value = std::get_if<uint64_t>(&val);
787ac6a4445SGunnar Mills                     if (value == nullptr)
788ac6a4445SGunnar Mills                     {
789ac6a4445SGunnar Mills                         messages::internalError(aResp->res);
790ac6a4445SGunnar Mills                         BMCWEB_LOG_DEBUG
791ac6a4445SGunnar Mills                             << "Invalid property type for SizeInKiB";
792601af5edSChicago Duan                         return;
793ac6a4445SGunnar Mills                     }
794ac6a4445SGunnar Mills                     partition["SizeMiB"] = (*value >> 10);
795ac6a4445SGunnar Mills                 }
796ac6a4445SGunnar Mills             }
797ac6a4445SGunnar Mills         },
798ac6a4445SGunnar Mills 
799ac6a4445SGunnar Mills         service, path, "org.freedesktop.DBus.Properties", "GetAll",
800ac6a4445SGunnar Mills         "xyz.openbmc_project.Inventory.Item.PersistentMemory.Partition");
801ac6a4445SGunnar Mills }
802ac6a4445SGunnar Mills 
8038d1b46d7Szhanghch05 inline void getDimmData(std::shared_ptr<bmcweb::AsyncResp> aResp,
804ac6a4445SGunnar Mills                         const std::string& dimmId)
805ac6a4445SGunnar Mills {
806ac6a4445SGunnar Mills     BMCWEB_LOG_DEBUG << "Get available system dimm resources.";
807ac6a4445SGunnar Mills     crow::connections::systemBus->async_method_call(
808ac6a4445SGunnar Mills         [dimmId, aResp{std::move(aResp)}](
809ac6a4445SGunnar Mills             const boost::system::error_code ec,
810*b9d36b47SEd Tanous             const dbus::utility::MapperGetSubTreeResponse& subtree) {
811ac6a4445SGunnar Mills             if (ec)
812ac6a4445SGunnar Mills             {
813ac6a4445SGunnar Mills                 BMCWEB_LOG_DEBUG << "DBUS response error";
814ac6a4445SGunnar Mills                 messages::internalError(aResp->res);
815ac6a4445SGunnar Mills 
816ac6a4445SGunnar Mills                 return;
817ac6a4445SGunnar Mills             }
818ac6a4445SGunnar Mills             bool found = false;
819ac6a4445SGunnar Mills             for (const auto& [path, object] : subtree)
820ac6a4445SGunnar Mills             {
821ac6a4445SGunnar Mills                 if (path.find(dimmId) != std::string::npos)
822ac6a4445SGunnar Mills                 {
823ac6a4445SGunnar Mills                     for (const auto& [service, interfaces] : object)
824ac6a4445SGunnar Mills                     {
825*b9d36b47SEd Tanous                         for (const auto& interface : interfaces)
826ac6a4445SGunnar Mills                         {
827*b9d36b47SEd Tanous                             if (interface ==
828*b9d36b47SEd Tanous                                 "xyz.openbmc_project.Inventory.Item.Dimm")
829*b9d36b47SEd Tanous                             {
830*b9d36b47SEd Tanous                                 getDimmDataByService(aResp, dimmId, service,
831*b9d36b47SEd Tanous                                                      path);
832ac6a4445SGunnar Mills                                 found = true;
833ac6a4445SGunnar Mills                             }
834ac6a4445SGunnar Mills 
835*b9d36b47SEd Tanous                             // partitions are separate as there can be multiple
836*b9d36b47SEd Tanous                             // per
837ac6a4445SGunnar Mills                             // device, i.e.
838ac6a4445SGunnar Mills                             // /xyz/openbmc_project/Inventory/Item/Dimm1/Partition1
839ac6a4445SGunnar Mills                             // /xyz/openbmc_project/Inventory/Item/Dimm1/Partition2
840*b9d36b47SEd Tanous                             if (interface ==
841*b9d36b47SEd Tanous                                 "xyz.openbmc_project.Inventory.Item.PersistentMemory.Partition")
842ac6a4445SGunnar Mills                             {
843ac6a4445SGunnar Mills                                 getDimmPartitionData(aResp, service, path);
844ac6a4445SGunnar Mills                             }
845ac6a4445SGunnar Mills                         }
846ac6a4445SGunnar Mills                     }
847ac6a4445SGunnar Mills                 }
848*b9d36b47SEd Tanous             }
849ac6a4445SGunnar Mills             // Object not found
850ac6a4445SGunnar Mills             if (!found)
851ac6a4445SGunnar Mills             {
852ac6a4445SGunnar Mills                 messages::resourceNotFound(aResp->res, "Memory", dimmId);
853ac6a4445SGunnar Mills             }
854ac6a4445SGunnar Mills             return;
855ac6a4445SGunnar Mills         },
856ac6a4445SGunnar Mills         "xyz.openbmc_project.ObjectMapper",
857ac6a4445SGunnar Mills         "/xyz/openbmc_project/object_mapper",
858ac6a4445SGunnar Mills         "xyz.openbmc_project.ObjectMapper", "GetSubTree",
859ac6a4445SGunnar Mills         "/xyz/openbmc_project/inventory", 0,
860ac6a4445SGunnar Mills         std::array<const char*, 2>{
861ac6a4445SGunnar Mills             "xyz.openbmc_project.Inventory.Item.Dimm",
862ac6a4445SGunnar Mills             "xyz.openbmc_project.Inventory.Item.PersistentMemory.Partition"});
863ac6a4445SGunnar Mills }
864ac6a4445SGunnar Mills 
8657e860f15SJohn Edward Broadbent inline void requestRoutesMemoryCollection(App& app)
866ac6a4445SGunnar Mills {
867ac6a4445SGunnar Mills     /**
868ac6a4445SGunnar Mills      * Functions triggers appropriate requests on DBus
869ac6a4445SGunnar Mills      */
8707e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/Memory/")
871ed398213SEd Tanous         .privileges(redfish::privileges::getMemoryCollection)
8727e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::get)(
8737e860f15SJohn Edward Broadbent             [](const crow::Request&,
8747e860f15SJohn Edward Broadbent                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
8758d1b46d7Szhanghch05                 asyncResp->res.jsonValue["@odata.type"] =
8768d1b46d7Szhanghch05                     "#MemoryCollection.MemoryCollection";
8778d1b46d7Szhanghch05                 asyncResp->res.jsonValue["Name"] = "Memory Module Collection";
8788d1b46d7Szhanghch05                 asyncResp->res.jsonValue["@odata.id"] =
8798d1b46d7Szhanghch05                     "/redfish/v1/Systems/system/Memory";
880ac6a4445SGunnar Mills 
88105030b8eSGunnar Mills                 collection_util::getCollectionMembers(
88205030b8eSGunnar Mills                     asyncResp, "/redfish/v1/Systems/system/Memory",
88305030b8eSGunnar Mills                     {"xyz.openbmc_project.Inventory.Item.Dimm"});
8847e860f15SJohn Edward Broadbent             });
885ac6a4445SGunnar Mills }
886ac6a4445SGunnar Mills 
8877e860f15SJohn Edward Broadbent inline void requestRoutesMemory(App& app)
8887e860f15SJohn Edward Broadbent {
889ac6a4445SGunnar Mills     /**
890ac6a4445SGunnar Mills      * Functions triggers appropriate requests on DBus
891ac6a4445SGunnar Mills      */
8927e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/Memory/<str>/")
893ed398213SEd Tanous         .privileges(redfish::privileges::getMemory)
8947e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::get)(
8957e860f15SJohn Edward Broadbent             [](const crow::Request&,
8967e860f15SJohn Edward Broadbent                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
8977e860f15SJohn Edward Broadbent                const std::string& dimmId) {
8987e860f15SJohn Edward Broadbent                 asyncResp->res.jsonValue["@odata.type"] =
8997e860f15SJohn Edward Broadbent                     "#Memory.v1_11_0.Memory";
9008d1b46d7Szhanghch05                 asyncResp->res.jsonValue["@odata.id"] =
901ac6a4445SGunnar Mills                     "/redfish/v1/Systems/system/Memory/" + dimmId;
902ac6a4445SGunnar Mills 
903ac6a4445SGunnar Mills                 getDimmData(asyncResp, dimmId);
9047e860f15SJohn Edward Broadbent             });
905ac6a4445SGunnar Mills }
906ac6a4445SGunnar Mills 
907ac6a4445SGunnar Mills } // namespace redfish
908