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 20ac6a4445SGunnar Mills #include <boost/container/flat_map.hpp> 21ac6a4445SGunnar Mills #include <boost/format.hpp> 22ac6a4445SGunnar Mills #include <node.hpp> 23ac6a4445SGunnar Mills #include <utils/collection.hpp> 24ac6a4445SGunnar Mills #include <utils/json_utils.hpp> 25ac6a4445SGunnar Mills 26ac6a4445SGunnar Mills namespace redfish 27ac6a4445SGunnar Mills { 28ac6a4445SGunnar Mills 29ac6a4445SGunnar Mills using DimmProperty = 30ac6a4445SGunnar Mills std::variant<std::string, std::vector<uint32_t>, std::vector<uint16_t>, 31ac6a4445SGunnar Mills uint64_t, uint32_t, uint16_t, uint8_t, bool>; 32ac6a4445SGunnar Mills 33ac6a4445SGunnar Mills using DimmProperties = boost::container::flat_map<std::string, DimmProperty>; 34ac6a4445SGunnar Mills 35*313efb1cSGunnar Mills inline std::string translateMemoryTypeToRedfish(const std::string& memoryType) 36*313efb1cSGunnar Mills { 37*313efb1cSGunnar Mills if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR") 38*313efb1cSGunnar Mills { 39*313efb1cSGunnar Mills return "DDR"; 40*313efb1cSGunnar Mills } 41*313efb1cSGunnar Mills if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR2") 42*313efb1cSGunnar Mills { 43*313efb1cSGunnar Mills return "DDR2"; 44*313efb1cSGunnar Mills } 45*313efb1cSGunnar Mills if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR3") 46*313efb1cSGunnar Mills { 47*313efb1cSGunnar Mills return "DDR3"; 48*313efb1cSGunnar Mills } 49*313efb1cSGunnar Mills if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR4") 50*313efb1cSGunnar Mills { 51*313efb1cSGunnar Mills return "DDR4"; 52*313efb1cSGunnar Mills } 53*313efb1cSGunnar Mills if (memoryType == 54*313efb1cSGunnar Mills "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR4E_SDRAM") 55*313efb1cSGunnar Mills { 56*313efb1cSGunnar Mills return "DDR4E_SDRAM"; 57*313efb1cSGunnar Mills } 58*313efb1cSGunnar Mills if (memoryType == 59*313efb1cSGunnar Mills "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.LPDDR4_SDRAM") 60*313efb1cSGunnar Mills { 61*313efb1cSGunnar Mills return "LPDDR4_SDRAM"; 62*313efb1cSGunnar Mills } 63*313efb1cSGunnar Mills if (memoryType == 64*313efb1cSGunnar Mills "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.LPDDR3_SDRAM") 65*313efb1cSGunnar Mills { 66*313efb1cSGunnar Mills return "LPDDR3_SDRAM"; 67*313efb1cSGunnar Mills } 68*313efb1cSGunnar Mills if (memoryType == 69*313efb1cSGunnar Mills "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR2_SDRAM_FB_DIMM") 70*313efb1cSGunnar Mills { 71*313efb1cSGunnar Mills return "DDR2_SDRAM_FB_DIMM"; 72*313efb1cSGunnar Mills } 73*313efb1cSGunnar Mills if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR2_" 74*313efb1cSGunnar Mills "SDRAM_FB_DIMM_PROB") 75*313efb1cSGunnar Mills { 76*313efb1cSGunnar Mills return "DDR2_SDRAM_FB_DIMM_PROBE"; 77*313efb1cSGunnar Mills } 78*313efb1cSGunnar Mills if (memoryType == 79*313efb1cSGunnar Mills "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.DDR_SGRAM") 80*313efb1cSGunnar Mills { 81*313efb1cSGunnar Mills return "DDR_SGRAM"; 82*313efb1cSGunnar Mills } 83*313efb1cSGunnar Mills if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.ROM") 84*313efb1cSGunnar Mills { 85*313efb1cSGunnar Mills return "ROM"; 86*313efb1cSGunnar Mills } 87*313efb1cSGunnar Mills if (memoryType == 88*313efb1cSGunnar Mills "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.SDRAM") 89*313efb1cSGunnar Mills { 90*313efb1cSGunnar Mills return "SDRAM"; 91*313efb1cSGunnar Mills } 92*313efb1cSGunnar Mills if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.EDO") 93*313efb1cSGunnar Mills { 94*313efb1cSGunnar Mills return "EDO"; 95*313efb1cSGunnar Mills } 96*313efb1cSGunnar Mills if (memoryType == 97*313efb1cSGunnar Mills "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.FastPageMode") 98*313efb1cSGunnar Mills { 99*313efb1cSGunnar Mills return "FastPageMode"; 100*313efb1cSGunnar Mills } 101*313efb1cSGunnar Mills if (memoryType == 102*313efb1cSGunnar Mills "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.PipelinedNibble") 103*313efb1cSGunnar Mills { 104*313efb1cSGunnar Mills return "PipelinedNibble"; 105*313efb1cSGunnar Mills } 106*313efb1cSGunnar Mills if (memoryType == 107*313efb1cSGunnar Mills "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.Logical") 108*313efb1cSGunnar Mills { 109*313efb1cSGunnar Mills return "Logical"; 110*313efb1cSGunnar Mills } 111*313efb1cSGunnar Mills if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.HBM") 112*313efb1cSGunnar Mills { 113*313efb1cSGunnar Mills return "HBM"; 114*313efb1cSGunnar Mills } 115*313efb1cSGunnar Mills if (memoryType == "xyz.openbmc_project.Inventory.Item.Dimm.DeviceType.HBM2") 116*313efb1cSGunnar Mills { 117*313efb1cSGunnar Mills return "HBM2"; 118*313efb1cSGunnar Mills } 119*313efb1cSGunnar Mills // This is values like Other or Unknown 120*313efb1cSGunnar Mills // Also D-Bus values: 121*313efb1cSGunnar Mills // DRAM 122*313efb1cSGunnar Mills // EDRAM 123*313efb1cSGunnar Mills // VRAM 124*313efb1cSGunnar Mills // SRAM 125*313efb1cSGunnar Mills // RAM 126*313efb1cSGunnar Mills // FLASH 127*313efb1cSGunnar Mills // EEPROM 128*313efb1cSGunnar Mills // FEPROM 129*313efb1cSGunnar Mills // EPROM 130*313efb1cSGunnar Mills // CDRAM 131*313efb1cSGunnar Mills // ThreeDRAM 132*313efb1cSGunnar Mills // RDRAM 133*313efb1cSGunnar Mills // FBD2 134*313efb1cSGunnar Mills // LPDDR_SDRAM 135*313efb1cSGunnar Mills // LPDDR2_SDRAM 136*313efb1cSGunnar Mills return ""; 137*313efb1cSGunnar Mills } 138*313efb1cSGunnar Mills 139ac6a4445SGunnar Mills inline void dimmPropToHex(const std::shared_ptr<AsyncResp>& aResp, 140ac6a4445SGunnar Mills const char* key, 141ac6a4445SGunnar Mills const std::pair<std::string, DimmProperty>& 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 151ac6a4445SGunnar Mills aResp->res.jsonValue[key] = (boost::format("0x%04x") % *value).str(); 152ac6a4445SGunnar Mills } 153ac6a4445SGunnar Mills 154ac6a4445SGunnar Mills inline void 155ac6a4445SGunnar Mills getPersistentMemoryProperties(const std::shared_ptr<AsyncResp>& aResp, 156ac6a4445SGunnar Mills const DimmProperties& properties) 157ac6a4445SGunnar Mills { 158ac6a4445SGunnar Mills for (const auto& property : properties) 159ac6a4445SGunnar Mills { 160ac6a4445SGunnar Mills if (property.first == "ModuleManufacturerID") 161ac6a4445SGunnar Mills { 162ac6a4445SGunnar Mills dimmPropToHex(aResp, "ModuleManufacturerID", property); 163ac6a4445SGunnar Mills } 164ac6a4445SGunnar Mills else if (property.first == "ModuleProductID") 165ac6a4445SGunnar Mills { 166ac6a4445SGunnar Mills dimmPropToHex(aResp, "ModuleProductID", property); 167ac6a4445SGunnar Mills } 168ac6a4445SGunnar Mills else if (property.first == "SubsystemVendorID") 169ac6a4445SGunnar Mills { 170ac6a4445SGunnar Mills dimmPropToHex(aResp, "MemorySubsystemControllerManufacturerID", 171ac6a4445SGunnar Mills property); 172ac6a4445SGunnar Mills } 173ac6a4445SGunnar Mills else if (property.first == "SubsystemDeviceID") 174ac6a4445SGunnar Mills { 175ac6a4445SGunnar Mills dimmPropToHex(aResp, "MemorySubsystemControllerProductID", 176ac6a4445SGunnar Mills property); 177ac6a4445SGunnar Mills } 178ac6a4445SGunnar Mills else if (property.first == "VolatileRegionSizeLimitInKiB") 179ac6a4445SGunnar Mills { 180ac6a4445SGunnar Mills const uint64_t* value = std::get_if<uint64_t>(&property.second); 181ac6a4445SGunnar Mills 182ac6a4445SGunnar Mills if (value == nullptr) 183ac6a4445SGunnar Mills { 184ac6a4445SGunnar Mills messages::internalError(aResp->res); 185ac6a4445SGunnar Mills BMCWEB_LOG_DEBUG << "Invalid property type for " 186ac6a4445SGunnar Mills "VolatileRegionSizeLimitKiB"; 187ac6a4445SGunnar Mills continue; 188ac6a4445SGunnar Mills } 189ac6a4445SGunnar Mills aResp->res.jsonValue["VolatileRegionSizeLimitMiB"] = (*value) >> 10; 190ac6a4445SGunnar Mills } 191ac6a4445SGunnar Mills else if (property.first == "PmRegionSizeLimitInKiB") 192ac6a4445SGunnar Mills { 193ac6a4445SGunnar Mills const uint64_t* value = std::get_if<uint64_t>(&property.second); 194ac6a4445SGunnar Mills 195ac6a4445SGunnar Mills if (value == nullptr) 196ac6a4445SGunnar Mills { 197ac6a4445SGunnar Mills messages::internalError(aResp->res); 198ac6a4445SGunnar Mills BMCWEB_LOG_DEBUG 199ac6a4445SGunnar Mills << "Invalid property type for PmRegioSizeLimitKiB"; 200ac6a4445SGunnar Mills continue; 201ac6a4445SGunnar Mills } 202ac6a4445SGunnar Mills aResp->res.jsonValue["PersistentRegionSizeLimitMiB"] = 203ac6a4445SGunnar Mills (*value) >> 10; 204ac6a4445SGunnar Mills } 205ac6a4445SGunnar Mills else if (property.first == "VolatileSizeInKiB") 206ac6a4445SGunnar Mills { 207ac6a4445SGunnar Mills const uint64_t* value = std::get_if<uint64_t>(&property.second); 208ac6a4445SGunnar Mills 209ac6a4445SGunnar Mills if (value == nullptr) 210ac6a4445SGunnar Mills { 211ac6a4445SGunnar Mills messages::internalError(aResp->res); 212ac6a4445SGunnar Mills BMCWEB_LOG_DEBUG 213ac6a4445SGunnar Mills << "Invalid property type for VolatileSizeInKiB"; 214ac6a4445SGunnar Mills continue; 215ac6a4445SGunnar Mills } 216ac6a4445SGunnar Mills aResp->res.jsonValue["VolatileSizeMiB"] = (*value) >> 10; 217ac6a4445SGunnar Mills } 218ac6a4445SGunnar Mills else if (property.first == "PmSizeInKiB") 219ac6a4445SGunnar Mills { 220ac6a4445SGunnar Mills const uint64_t* value = std::get_if<uint64_t>(&property.second); 221ac6a4445SGunnar Mills if (value == nullptr) 222ac6a4445SGunnar Mills { 223ac6a4445SGunnar Mills messages::internalError(aResp->res); 224ac6a4445SGunnar Mills BMCWEB_LOG_DEBUG << "Invalid property type for PmSizeInKiB"; 225ac6a4445SGunnar Mills continue; 226ac6a4445SGunnar Mills } 227ac6a4445SGunnar Mills aResp->res.jsonValue["NonVolatileSizeMiB"] = (*value) >> 10; 228ac6a4445SGunnar Mills } 229ac6a4445SGunnar Mills else if (property.first == "CacheSizeInKB") 230ac6a4445SGunnar Mills { 231ac6a4445SGunnar Mills const uint64_t* value = std::get_if<uint64_t>(&property.second); 232ac6a4445SGunnar Mills if (value == nullptr) 233ac6a4445SGunnar Mills { 234ac6a4445SGunnar Mills messages::internalError(aResp->res); 235ac6a4445SGunnar Mills BMCWEB_LOG_DEBUG << "Invalid property type for CacheSizeInKB"; 236ac6a4445SGunnar Mills continue; 237ac6a4445SGunnar Mills } 238ac6a4445SGunnar Mills aResp->res.jsonValue["CacheSizeMiB"] = (*value >> 10); 239ac6a4445SGunnar Mills } 240ac6a4445SGunnar Mills 241ac6a4445SGunnar Mills else if (property.first == "VoltaileRegionMaxSizeInKib") 242ac6a4445SGunnar Mills { 243ac6a4445SGunnar Mills const uint64_t* value = std::get_if<uint64_t>(&property.second); 244ac6a4445SGunnar Mills 245ac6a4445SGunnar Mills if (value == nullptr) 246ac6a4445SGunnar Mills { 247ac6a4445SGunnar Mills messages::internalError(aResp->res); 248ac6a4445SGunnar Mills BMCWEB_LOG_DEBUG << "Invalid property type for " 249ac6a4445SGunnar Mills "VolatileRegionMaxSizeInKib"; 250ac6a4445SGunnar Mills continue; 251ac6a4445SGunnar Mills } 252ac6a4445SGunnar Mills aResp->res.jsonValue["VolatileRegionSizeMaxMiB"] = (*value) >> 10; 253ac6a4445SGunnar Mills } 254ac6a4445SGunnar Mills else if (property.first == "PmRegionMaxSizeInKiB") 255ac6a4445SGunnar Mills { 256ac6a4445SGunnar Mills const uint64_t* value = std::get_if<uint64_t>(&property.second); 257ac6a4445SGunnar Mills 258ac6a4445SGunnar Mills if (value == nullptr) 259ac6a4445SGunnar Mills { 260ac6a4445SGunnar Mills messages::internalError(aResp->res); 261ac6a4445SGunnar Mills BMCWEB_LOG_DEBUG 262ac6a4445SGunnar Mills << "Invalid property type for PmRegionMaxSizeInKiB"; 263ac6a4445SGunnar Mills continue; 264ac6a4445SGunnar Mills } 265ac6a4445SGunnar Mills aResp->res.jsonValue["PersistentRegionSizeMaxMiB"] = (*value) >> 10; 266ac6a4445SGunnar Mills } 267ac6a4445SGunnar Mills else if (property.first == "AllocationIncrementInKiB") 268ac6a4445SGunnar Mills { 269ac6a4445SGunnar Mills const uint64_t* value = std::get_if<uint64_t>(&property.second); 270ac6a4445SGunnar Mills 271ac6a4445SGunnar Mills if (value == nullptr) 272ac6a4445SGunnar Mills { 273ac6a4445SGunnar Mills messages::internalError(aResp->res); 274ac6a4445SGunnar Mills BMCWEB_LOG_DEBUG << "Invalid property type for " 275ac6a4445SGunnar Mills "AllocationIncrementInKiB"; 276ac6a4445SGunnar Mills continue; 277ac6a4445SGunnar Mills } 278ac6a4445SGunnar Mills aResp->res.jsonValue["AllocationIncrementMiB"] = (*value) >> 10; 279ac6a4445SGunnar Mills } 280ac6a4445SGunnar Mills else if (property.first == "AllocationAlignmentInKiB") 281ac6a4445SGunnar Mills { 282ac6a4445SGunnar Mills const uint64_t* value = std::get_if<uint64_t>(&property.second); 283ac6a4445SGunnar Mills 284ac6a4445SGunnar Mills if (value == nullptr) 285ac6a4445SGunnar Mills { 286ac6a4445SGunnar Mills messages::internalError(aResp->res); 287ac6a4445SGunnar Mills BMCWEB_LOG_DEBUG << "Invalid property type for " 288ac6a4445SGunnar Mills "AllocationAlignmentInKiB"; 289ac6a4445SGunnar Mills continue; 290ac6a4445SGunnar Mills } 291ac6a4445SGunnar Mills aResp->res.jsonValue["AllocationAlignmentMiB"] = (*value) >> 10; 292ac6a4445SGunnar Mills } 293ac6a4445SGunnar Mills else if (property.first == "VolatileRegionNumberLimit") 294ac6a4445SGunnar Mills { 295ac6a4445SGunnar Mills const uint64_t* value = std::get_if<uint64_t>(&property.second); 296ac6a4445SGunnar Mills if (value == nullptr) 297ac6a4445SGunnar Mills { 298ac6a4445SGunnar Mills messages::internalError(aResp->res); 299ac6a4445SGunnar Mills continue; 300ac6a4445SGunnar Mills } 301ac6a4445SGunnar Mills aResp->res.jsonValue["VolatileRegionNumberLimit"] = *value; 302ac6a4445SGunnar Mills } 303ac6a4445SGunnar Mills else if (property.first == "PmRegionNumberLimit") 304ac6a4445SGunnar Mills { 305ac6a4445SGunnar Mills const uint64_t* value = std::get_if<uint64_t>(&property.second); 306ac6a4445SGunnar Mills if (value == nullptr) 307ac6a4445SGunnar Mills { 308ac6a4445SGunnar Mills messages::internalError(aResp->res); 309ac6a4445SGunnar Mills continue; 310ac6a4445SGunnar Mills } 311ac6a4445SGunnar Mills aResp->res.jsonValue["PersistentRegionNumberLimit"] = *value; 312ac6a4445SGunnar Mills } 313ac6a4445SGunnar Mills else if (property.first == "SpareDeviceCount") 314ac6a4445SGunnar Mills { 315ac6a4445SGunnar Mills const uint64_t* value = std::get_if<uint64_t>(&property.second); 316ac6a4445SGunnar Mills if (value == nullptr) 317ac6a4445SGunnar Mills { 318ac6a4445SGunnar Mills messages::internalError(aResp->res); 319ac6a4445SGunnar Mills continue; 320ac6a4445SGunnar Mills } 321ac6a4445SGunnar Mills aResp->res.jsonValue["SpareDeviceCount"] = *value; 322ac6a4445SGunnar Mills } 323ac6a4445SGunnar Mills else if (property.first == "IsSpareDeviceInUse") 324ac6a4445SGunnar Mills { 325ac6a4445SGunnar Mills const bool* value = std::get_if<bool>(&property.second); 326ac6a4445SGunnar Mills if (value == nullptr) 327ac6a4445SGunnar Mills { 328ac6a4445SGunnar Mills messages::internalError(aResp->res); 329ac6a4445SGunnar Mills continue; 330ac6a4445SGunnar Mills } 331ac6a4445SGunnar Mills aResp->res.jsonValue["IsSpareDeviceEnabled"] = *value; 332ac6a4445SGunnar Mills } 333ac6a4445SGunnar Mills else if (property.first == "IsRankSpareEnabled") 334ac6a4445SGunnar Mills { 335ac6a4445SGunnar Mills const bool* value = std::get_if<bool>(&property.second); 336ac6a4445SGunnar Mills if (value == nullptr) 337ac6a4445SGunnar Mills { 338ac6a4445SGunnar Mills messages::internalError(aResp->res); 339ac6a4445SGunnar Mills continue; 340ac6a4445SGunnar Mills } 341ac6a4445SGunnar Mills aResp->res.jsonValue["IsRankSpareEnabled"] = *value; 342ac6a4445SGunnar Mills } 343ac6a4445SGunnar Mills else if (property.first == "MaxAveragePowerLimitmW") 344ac6a4445SGunnar Mills { 345ac6a4445SGunnar Mills const auto* value = 346ac6a4445SGunnar Mills std::get_if<std::vector<uint32_t>>(&property.second); 347ac6a4445SGunnar Mills if (value == nullptr) 348ac6a4445SGunnar Mills { 349ac6a4445SGunnar Mills messages::internalError(aResp->res); 350ac6a4445SGunnar Mills BMCWEB_LOG_DEBUG << "Invalid property type for " 351ac6a4445SGunnar Mills "MaxAveragePowerLimitmW"; 352ac6a4445SGunnar Mills continue; 353ac6a4445SGunnar Mills } 354ac6a4445SGunnar Mills aResp->res.jsonValue["MaxTDPMilliWatts"] = *value; 355ac6a4445SGunnar Mills } 356ac6a4445SGunnar Mills else if (property.first == "ConfigurationLocked") 357ac6a4445SGunnar Mills { 358ac6a4445SGunnar Mills const bool* value = std::get_if<bool>(&property.second); 359ac6a4445SGunnar Mills if (value == nullptr) 360ac6a4445SGunnar Mills { 361ac6a4445SGunnar Mills messages::internalError(aResp->res); 362ac6a4445SGunnar Mills continue; 363ac6a4445SGunnar Mills } 364ac6a4445SGunnar Mills aResp->res.jsonValue["ConfigurationLocked"] = *value; 365ac6a4445SGunnar Mills } 366ac6a4445SGunnar Mills else if (property.first == "AllowedMemoryModes") 367ac6a4445SGunnar Mills { 368ac6a4445SGunnar Mills const std::string* value = 369ac6a4445SGunnar Mills std::get_if<std::string>(&property.second); 370ac6a4445SGunnar Mills if (value == nullptr) 371ac6a4445SGunnar Mills { 372ac6a4445SGunnar Mills messages::internalError(aResp->res); 373ac6a4445SGunnar Mills BMCWEB_LOG_DEBUG << "Invalid property type for FormFactor"; 374ac6a4445SGunnar Mills continue; 375ac6a4445SGunnar Mills } 376ac6a4445SGunnar Mills constexpr const std::array<const char*, 3> values{"Volatile", 377ac6a4445SGunnar Mills "PMEM", "Block"}; 378ac6a4445SGunnar Mills 379ac6a4445SGunnar Mills for (const char* v : values) 380ac6a4445SGunnar Mills { 381ac6a4445SGunnar Mills if (boost::ends_with(*value, v)) 382ac6a4445SGunnar Mills { 383ac6a4445SGunnar Mills aResp->res.jsonValue["OperatingMemoryModes "] = v; 384ac6a4445SGunnar Mills break; 385ac6a4445SGunnar Mills } 386ac6a4445SGunnar Mills } 387ac6a4445SGunnar Mills } 388ac6a4445SGunnar Mills else if (property.first == "MemoryMedia") 389ac6a4445SGunnar Mills { 390ac6a4445SGunnar Mills const std::string* value = 391ac6a4445SGunnar Mills std::get_if<std::string>(&property.second); 392ac6a4445SGunnar Mills if (value == nullptr) 393ac6a4445SGunnar Mills { 394ac6a4445SGunnar Mills messages::internalError(aResp->res); 395ac6a4445SGunnar Mills BMCWEB_LOG_DEBUG << "Invalid property type for MemoryMedia"; 396ac6a4445SGunnar Mills continue; 397ac6a4445SGunnar Mills } 398ac6a4445SGunnar Mills constexpr const std::array<const char*, 3> values{"DRAM", "NAND", 399ac6a4445SGunnar Mills "Intel3DXPoint"}; 400ac6a4445SGunnar Mills 401ac6a4445SGunnar Mills for (const char* v : values) 402ac6a4445SGunnar Mills { 403ac6a4445SGunnar Mills if (boost::ends_with(*value, v)) 404ac6a4445SGunnar Mills { 405ac6a4445SGunnar Mills aResp->res.jsonValue["MemoryMedia"] = v; 406ac6a4445SGunnar Mills break; 407ac6a4445SGunnar Mills } 408ac6a4445SGunnar Mills } 409ac6a4445SGunnar Mills } 410ac6a4445SGunnar Mills // PersistantMemory.SecurityCapabilites interface 411ac6a4445SGunnar Mills else if (property.first == "ConfigurationLockCapable" || 412ac6a4445SGunnar Mills property.first == "DataLockCapable" || 413ac6a4445SGunnar Mills property.first == "PassphraseCapable") 414ac6a4445SGunnar Mills { 415ac6a4445SGunnar Mills const bool* value = std::get_if<bool>(&property.second); 416ac6a4445SGunnar Mills if (value == nullptr) 417ac6a4445SGunnar Mills { 418ac6a4445SGunnar Mills messages::internalError(aResp->res); 419ac6a4445SGunnar Mills continue; 420ac6a4445SGunnar Mills } 421ac6a4445SGunnar Mills aResp->res.jsonValue["SecurityCapabilities"][property.first] = 422ac6a4445SGunnar Mills *value; 423ac6a4445SGunnar Mills } 424ac6a4445SGunnar Mills else if (property.first == "MaxPassphraseCount" || 425ac6a4445SGunnar Mills property.first == "PassphraseLockLimit") 426ac6a4445SGunnar Mills { 427ac6a4445SGunnar Mills const uint64_t* value = std::get_if<uint64_t>(&property.second); 428ac6a4445SGunnar Mills if (value == nullptr) 429ac6a4445SGunnar Mills { 430ac6a4445SGunnar Mills messages::internalError(aResp->res); 431ac6a4445SGunnar Mills continue; 432ac6a4445SGunnar Mills } 433ac6a4445SGunnar Mills aResp->res.jsonValue["SecurityCapabilities"][property.first] = 434ac6a4445SGunnar Mills *value; 435ac6a4445SGunnar Mills } 436ac6a4445SGunnar Mills } 437ac6a4445SGunnar Mills } 438ac6a4445SGunnar Mills 439ac6a4445SGunnar Mills inline void getDimmDataByService(std::shared_ptr<AsyncResp> aResp, 440ac6a4445SGunnar Mills const std::string& dimmId, 441ac6a4445SGunnar Mills const std::string& service, 442ac6a4445SGunnar Mills const std::string& objPath) 443ac6a4445SGunnar Mills { 444ac6a4445SGunnar Mills auto health = std::make_shared<HealthPopulate>(aResp); 445ac6a4445SGunnar Mills health->selfPath = objPath; 446ac6a4445SGunnar Mills health->populate(); 447ac6a4445SGunnar Mills 448ac6a4445SGunnar Mills BMCWEB_LOG_DEBUG << "Get available system components."; 449ac6a4445SGunnar Mills crow::connections::systemBus->async_method_call( 450ac6a4445SGunnar Mills [dimmId, aResp{std::move(aResp)}](const boost::system::error_code ec, 451ac6a4445SGunnar Mills const DimmProperties& properties) { 452ac6a4445SGunnar Mills if (ec) 453ac6a4445SGunnar Mills { 454ac6a4445SGunnar Mills BMCWEB_LOG_DEBUG << "DBUS response error"; 455ac6a4445SGunnar Mills messages::internalError(aResp->res); 456ac6a4445SGunnar Mills 457ac6a4445SGunnar Mills return; 458ac6a4445SGunnar Mills } 459ac6a4445SGunnar Mills aResp->res.jsonValue["Id"] = dimmId; 460ac6a4445SGunnar Mills aResp->res.jsonValue["Name"] = "DIMM Slot"; 461ac6a4445SGunnar Mills 462ac6a4445SGunnar Mills const auto memorySizeProperty = properties.find("MemorySizeInKB"); 463ac6a4445SGunnar Mills if (memorySizeProperty != properties.end()) 464ac6a4445SGunnar Mills { 465ac6a4445SGunnar Mills const uint32_t* memorySize = 466ac6a4445SGunnar Mills std::get_if<uint32_t>(&memorySizeProperty->second); 467ac6a4445SGunnar Mills if (memorySize == nullptr) 468ac6a4445SGunnar Mills { 469ac6a4445SGunnar Mills // Important property not in desired type 470ac6a4445SGunnar Mills messages::internalError(aResp->res); 471ac6a4445SGunnar Mills 472ac6a4445SGunnar Mills return; 473ac6a4445SGunnar Mills } 474ac6a4445SGunnar Mills if (*memorySize == 0) 475ac6a4445SGunnar Mills { 476ac6a4445SGunnar Mills // Slot is not populated, set status end return 477ac6a4445SGunnar Mills aResp->res.jsonValue["Status"]["State"] = "Absent"; 478ac6a4445SGunnar Mills aResp->res.jsonValue["Status"]["Health"] = "OK"; 479ac6a4445SGunnar Mills // HTTP Code will be set up automatically, just return 480ac6a4445SGunnar Mills return; 481ac6a4445SGunnar Mills } 482ac6a4445SGunnar Mills aResp->res.jsonValue["CapacityMiB"] = (*memorySize >> 10); 483ac6a4445SGunnar Mills } 484ac6a4445SGunnar Mills aResp->res.jsonValue["Status"]["State"] = "Enabled"; 485ac6a4445SGunnar Mills aResp->res.jsonValue["Status"]["Health"] = "OK"; 486ac6a4445SGunnar Mills 487ac6a4445SGunnar Mills for (const auto& property : properties) 488ac6a4445SGunnar Mills { 489ac6a4445SGunnar Mills if (property.first == "MemoryDataWidth") 490ac6a4445SGunnar Mills { 491ac6a4445SGunnar Mills const uint16_t* value = 492ac6a4445SGunnar Mills std::get_if<uint16_t>(&property.second); 493ac6a4445SGunnar Mills if (value == nullptr) 494ac6a4445SGunnar Mills { 495ac6a4445SGunnar Mills continue; 496ac6a4445SGunnar Mills } 497ac6a4445SGunnar Mills aResp->res.jsonValue["DataWidthBits"] = *value; 498ac6a4445SGunnar Mills } 499ac6a4445SGunnar Mills else if (property.first == "PartNumber") 500ac6a4445SGunnar Mills { 501ac6a4445SGunnar Mills const std::string* value = 502ac6a4445SGunnar Mills std::get_if<std::string>(&property.second); 503ac6a4445SGunnar Mills if (value == nullptr) 504ac6a4445SGunnar Mills { 505ac6a4445SGunnar Mills continue; 506ac6a4445SGunnar Mills } 507ac6a4445SGunnar Mills aResp->res.jsonValue["PartNumber"] = *value; 508ac6a4445SGunnar Mills } 509ac6a4445SGunnar Mills else if (property.first == "SerialNumber") 510ac6a4445SGunnar Mills { 511ac6a4445SGunnar Mills const std::string* value = 512ac6a4445SGunnar Mills std::get_if<std::string>(&property.second); 513ac6a4445SGunnar Mills if (value == nullptr) 514ac6a4445SGunnar Mills { 515ac6a4445SGunnar Mills continue; 516ac6a4445SGunnar Mills } 517ac6a4445SGunnar Mills aResp->res.jsonValue["SerialNumber"] = *value; 518ac6a4445SGunnar Mills } 519ac6a4445SGunnar Mills else if (property.first == "Manufacturer") 520ac6a4445SGunnar Mills { 521ac6a4445SGunnar Mills const std::string* value = 522ac6a4445SGunnar Mills std::get_if<std::string>(&property.second); 523ac6a4445SGunnar Mills if (value == nullptr) 524ac6a4445SGunnar Mills { 525ac6a4445SGunnar Mills continue; 526ac6a4445SGunnar Mills } 527ac6a4445SGunnar Mills aResp->res.jsonValue["Manufacturer"] = *value; 528ac6a4445SGunnar Mills } 529ac6a4445SGunnar Mills else if (property.first == "RevisionCode") 530ac6a4445SGunnar Mills { 531ac6a4445SGunnar Mills const uint16_t* value = 532ac6a4445SGunnar Mills std::get_if<uint16_t>(&property.second); 533ac6a4445SGunnar Mills 534ac6a4445SGunnar Mills if (value == nullptr) 535ac6a4445SGunnar Mills { 536ac6a4445SGunnar Mills messages::internalError(aResp->res); 537ac6a4445SGunnar Mills BMCWEB_LOG_DEBUG 538ac6a4445SGunnar Mills << "Invalid property type for RevisionCode"; 539ac6a4445SGunnar Mills continue; 540ac6a4445SGunnar Mills } 541ac6a4445SGunnar Mills aResp->res.jsonValue["FirmwareRevision"] = 542ac6a4445SGunnar Mills std::to_string(*value); 543ac6a4445SGunnar Mills } 544ac6a4445SGunnar Mills else if (property.first == "MemoryTotalWidth") 545ac6a4445SGunnar Mills { 546ac6a4445SGunnar Mills const uint16_t* value = 547ac6a4445SGunnar Mills std::get_if<uint16_t>(&property.second); 548ac6a4445SGunnar Mills if (value == nullptr) 549ac6a4445SGunnar Mills { 550ac6a4445SGunnar Mills continue; 551ac6a4445SGunnar Mills } 552ac6a4445SGunnar Mills aResp->res.jsonValue["BusWidthBits"] = *value; 553ac6a4445SGunnar Mills } 554ac6a4445SGunnar Mills else if (property.first == "ECC") 555ac6a4445SGunnar Mills { 556ac6a4445SGunnar Mills const std::string* value = 557ac6a4445SGunnar Mills std::get_if<std::string>(&property.second); 558ac6a4445SGunnar Mills if (value == nullptr) 559ac6a4445SGunnar Mills { 560ac6a4445SGunnar Mills messages::internalError(aResp->res); 561ac6a4445SGunnar Mills BMCWEB_LOG_DEBUG << "Invalid property type for ECC"; 562ac6a4445SGunnar Mills continue; 563ac6a4445SGunnar Mills } 564ac6a4445SGunnar Mills constexpr const std::array<const char*, 4> values{ 565ac6a4445SGunnar Mills "NoECC", "SingleBitECC", "MultiBitECC", 566ac6a4445SGunnar Mills "AddressParity"}; 567ac6a4445SGunnar Mills 568ac6a4445SGunnar Mills for (const char* v : values) 569ac6a4445SGunnar Mills { 570ac6a4445SGunnar Mills if (boost::ends_with(*value, v)) 571ac6a4445SGunnar Mills { 572ac6a4445SGunnar Mills aResp->res.jsonValue["ErrorCorrection"] = v; 573ac6a4445SGunnar Mills break; 574ac6a4445SGunnar Mills } 575ac6a4445SGunnar Mills } 576ac6a4445SGunnar Mills } 577ac6a4445SGunnar Mills else if (property.first == "FormFactor") 578ac6a4445SGunnar Mills { 579ac6a4445SGunnar Mills const std::string* value = 580ac6a4445SGunnar Mills std::get_if<std::string>(&property.second); 581ac6a4445SGunnar Mills if (value == nullptr) 582ac6a4445SGunnar Mills { 583ac6a4445SGunnar Mills messages::internalError(aResp->res); 584ac6a4445SGunnar Mills BMCWEB_LOG_DEBUG 585ac6a4445SGunnar Mills << "Invalid property type for FormFactor"; 586ac6a4445SGunnar Mills continue; 587ac6a4445SGunnar Mills } 588ac6a4445SGunnar Mills constexpr const std::array<const char*, 11> values{ 589ac6a4445SGunnar Mills "RDIMM", "UDIMM", "SO_DIMM", 590ac6a4445SGunnar Mills "LRDIMM", "Mini_RDIMM", "Mini_UDIMM", 591ac6a4445SGunnar Mills "SO_RDIMM_72b", "SO_UDIMM_72b", "SO_DIMM_16b", 592ac6a4445SGunnar Mills "SO_DIMM_32b", "Die"}; 593ac6a4445SGunnar Mills 594ac6a4445SGunnar Mills for (const char* v : values) 595ac6a4445SGunnar Mills { 596ac6a4445SGunnar Mills if (boost::ends_with(*value, v)) 597ac6a4445SGunnar Mills { 598ac6a4445SGunnar Mills aResp->res.jsonValue["BaseModuleType"] = v; 599ac6a4445SGunnar Mills break; 600ac6a4445SGunnar Mills } 601ac6a4445SGunnar Mills } 602ac6a4445SGunnar Mills } 603ac6a4445SGunnar Mills else if (property.first == "AllowedSpeedsMT") 604ac6a4445SGunnar Mills { 605ac6a4445SGunnar Mills const std::vector<uint16_t>* value = 606ac6a4445SGunnar Mills std::get_if<std::vector<uint16_t>>(&property.second); 607ac6a4445SGunnar Mills if (value == nullptr) 608ac6a4445SGunnar Mills { 609ac6a4445SGunnar Mills continue; 610ac6a4445SGunnar Mills } 611ac6a4445SGunnar Mills nlohmann::json& jValue = 612ac6a4445SGunnar Mills aResp->res.jsonValue["AllowedSpeedsMHz"]; 613ac6a4445SGunnar Mills jValue = nlohmann::json::array(); 614ac6a4445SGunnar Mills for (uint16_t subVal : *value) 615ac6a4445SGunnar Mills { 616ac6a4445SGunnar Mills jValue.push_back(subVal); 617ac6a4445SGunnar Mills } 618ac6a4445SGunnar Mills } 619ac6a4445SGunnar Mills else if (property.first == "MemoryAttributes") 620ac6a4445SGunnar Mills { 621ac6a4445SGunnar Mills const uint8_t* value = 622ac6a4445SGunnar Mills std::get_if<uint8_t>(&property.second); 623ac6a4445SGunnar Mills 624ac6a4445SGunnar Mills if (value == nullptr) 625ac6a4445SGunnar Mills { 626ac6a4445SGunnar Mills messages::internalError(aResp->res); 627ac6a4445SGunnar Mills BMCWEB_LOG_DEBUG 628ac6a4445SGunnar Mills << "Invalid property type for MemoryAttributes"; 629ac6a4445SGunnar Mills continue; 630ac6a4445SGunnar Mills } 631ac6a4445SGunnar Mills aResp->res.jsonValue["RankCount"] = 632ac6a4445SGunnar Mills static_cast<uint64_t>(*value); 633ac6a4445SGunnar Mills } 634ac6a4445SGunnar Mills else if (property.first == "MemoryConfiguredSpeedInMhz") 635ac6a4445SGunnar Mills { 636ac6a4445SGunnar Mills const uint16_t* value = 637ac6a4445SGunnar Mills std::get_if<uint16_t>(&property.second); 638ac6a4445SGunnar Mills if (value == nullptr) 639ac6a4445SGunnar Mills { 640ac6a4445SGunnar Mills continue; 641ac6a4445SGunnar Mills } 642ac6a4445SGunnar Mills aResp->res.jsonValue["OperatingSpeedMhz"] = *value; 643ac6a4445SGunnar Mills } 644ac6a4445SGunnar Mills else if (property.first == "MemoryType") 645ac6a4445SGunnar Mills { 646ac6a4445SGunnar Mills const auto* value = 647ac6a4445SGunnar Mills std::get_if<std::string>(&property.second); 648ac6a4445SGunnar Mills if (value != nullptr) 649ac6a4445SGunnar Mills { 650*313efb1cSGunnar Mills std::string memoryDeviceType = 651*313efb1cSGunnar Mills translateMemoryTypeToRedfish(*value); 652*313efb1cSGunnar Mills // Values like "Unknown" or "Other" will return empty 653*313efb1cSGunnar Mills // so just leave off 654*313efb1cSGunnar Mills if (!memoryDeviceType.empty()) 655ac6a4445SGunnar Mills { 656*313efb1cSGunnar Mills aResp->res.jsonValue["MemoryDeviceType"] = 657*313efb1cSGunnar Mills memoryDeviceType; 658ac6a4445SGunnar Mills } 659ac6a4445SGunnar Mills if (value->find("DDR") != std::string::npos) 660ac6a4445SGunnar Mills { 661ac6a4445SGunnar Mills aResp->res.jsonValue["MemoryType"] = "DRAM"; 662ac6a4445SGunnar Mills } 663ac6a4445SGunnar Mills else if (boost::ends_with(*value, "Logical")) 664ac6a4445SGunnar Mills { 665ac6a4445SGunnar Mills aResp->res.jsonValue["MemoryType"] = "IntelOptane"; 666ac6a4445SGunnar Mills } 667ac6a4445SGunnar Mills } 668ac6a4445SGunnar Mills } 669ac6a4445SGunnar Mills // memory location interface 670ac6a4445SGunnar Mills else if (property.first == "Channel" || 671ac6a4445SGunnar Mills property.first == "MemoryController" || 672ac6a4445SGunnar Mills property.first == "Slot" || property.first == "Socket") 673ac6a4445SGunnar Mills { 674ac6a4445SGunnar Mills const std::string* value = 675ac6a4445SGunnar Mills std::get_if<std::string>(&property.second); 676ac6a4445SGunnar Mills if (value == nullptr) 677ac6a4445SGunnar Mills { 678ac6a4445SGunnar Mills messages::internalError(aResp->res); 679ac6a4445SGunnar Mills continue; 680ac6a4445SGunnar Mills } 681ac6a4445SGunnar Mills aResp->res.jsonValue["MemoryLocation"][property.first] = 682ac6a4445SGunnar Mills *value; 683ac6a4445SGunnar Mills } 684ac6a4445SGunnar Mills else 685ac6a4445SGunnar Mills { 686ac6a4445SGunnar Mills getPersistentMemoryProperties(aResp, properties); 687ac6a4445SGunnar Mills } 688ac6a4445SGunnar Mills } 689ac6a4445SGunnar Mills }, 690ac6a4445SGunnar Mills service, objPath, "org.freedesktop.DBus.Properties", "GetAll", ""); 691ac6a4445SGunnar Mills } 692ac6a4445SGunnar Mills 693ac6a4445SGunnar Mills inline void getDimmPartitionData(std::shared_ptr<AsyncResp> aResp, 694ac6a4445SGunnar Mills const std::string& service, 695ac6a4445SGunnar Mills const std::string& path) 696ac6a4445SGunnar Mills { 697ac6a4445SGunnar Mills crow::connections::systemBus->async_method_call( 698ac6a4445SGunnar Mills [aResp{std::move(aResp)}]( 699ac6a4445SGunnar Mills const boost::system::error_code ec, 700ac6a4445SGunnar Mills const boost::container::flat_map< 701ac6a4445SGunnar Mills std::string, std::variant<std::string, uint64_t, uint32_t, 702ac6a4445SGunnar Mills bool>>& properties) { 703ac6a4445SGunnar Mills if (ec) 704ac6a4445SGunnar Mills { 705ac6a4445SGunnar Mills BMCWEB_LOG_DEBUG << "DBUS response error"; 706ac6a4445SGunnar Mills messages::internalError(aResp->res); 707ac6a4445SGunnar Mills 708ac6a4445SGunnar Mills return; 709ac6a4445SGunnar Mills } 710ac6a4445SGunnar Mills 711ac6a4445SGunnar Mills nlohmann::json& partition = 712ac6a4445SGunnar Mills aResp->res.jsonValue["Regions"].emplace_back( 713ac6a4445SGunnar Mills nlohmann::json::object()); 714ac6a4445SGunnar Mills for (const auto& [key, val] : properties) 715ac6a4445SGunnar Mills { 716ac6a4445SGunnar Mills if (key == "MemoryClassification") 717ac6a4445SGunnar Mills { 718ac6a4445SGunnar Mills const std::string* value = std::get_if<std::string>(&val); 719ac6a4445SGunnar Mills if (value == nullptr) 720ac6a4445SGunnar Mills { 721ac6a4445SGunnar Mills messages::internalError(aResp->res); 722ac6a4445SGunnar Mills continue; 723ac6a4445SGunnar Mills } 724ac6a4445SGunnar Mills partition[key] = *value; 725ac6a4445SGunnar Mills } 726ac6a4445SGunnar Mills else if (key == "OffsetInKiB") 727ac6a4445SGunnar Mills { 728ac6a4445SGunnar Mills const uint64_t* value = std::get_if<uint64_t>(&val); 729ac6a4445SGunnar Mills if (value == nullptr) 730ac6a4445SGunnar Mills { 731ac6a4445SGunnar Mills messages::internalError(aResp->res); 732ac6a4445SGunnar Mills continue; 733ac6a4445SGunnar Mills } 734ac6a4445SGunnar Mills 735ac6a4445SGunnar Mills partition["OffsetMiB"] = (*value >> 10); 736ac6a4445SGunnar Mills } 737ac6a4445SGunnar Mills else if (key == "PartitionId") 738ac6a4445SGunnar Mills { 739ac6a4445SGunnar Mills const std::string* value = std::get_if<std::string>(&val); 740ac6a4445SGunnar Mills if (value == nullptr) 741ac6a4445SGunnar Mills { 742ac6a4445SGunnar Mills messages::internalError(aResp->res); 743ac6a4445SGunnar Mills continue; 744ac6a4445SGunnar Mills } 745ac6a4445SGunnar Mills partition["RegionId"] = *value; 746ac6a4445SGunnar Mills } 747ac6a4445SGunnar Mills 748ac6a4445SGunnar Mills else if (key == "PassphraseState") 749ac6a4445SGunnar Mills { 750ac6a4445SGunnar Mills const bool* value = std::get_if<bool>(&val); 751ac6a4445SGunnar Mills if (value == nullptr) 752ac6a4445SGunnar Mills { 753ac6a4445SGunnar Mills messages::internalError(aResp->res); 754ac6a4445SGunnar Mills continue; 755ac6a4445SGunnar Mills } 756ac6a4445SGunnar Mills partition["PassphraseEnabled"] = *value; 757ac6a4445SGunnar Mills } 758ac6a4445SGunnar Mills else if (key == "SizeInKiB") 759ac6a4445SGunnar Mills { 760ac6a4445SGunnar Mills const uint64_t* value = std::get_if<uint64_t>(&val); 761ac6a4445SGunnar Mills if (value == nullptr) 762ac6a4445SGunnar Mills { 763ac6a4445SGunnar Mills messages::internalError(aResp->res); 764ac6a4445SGunnar Mills BMCWEB_LOG_DEBUG 765ac6a4445SGunnar Mills << "Invalid property type for SizeInKiB"; 766ac6a4445SGunnar Mills continue; 767ac6a4445SGunnar Mills } 768ac6a4445SGunnar Mills partition["SizeMiB"] = (*value >> 10); 769ac6a4445SGunnar Mills } 770ac6a4445SGunnar Mills } 771ac6a4445SGunnar Mills }, 772ac6a4445SGunnar Mills 773ac6a4445SGunnar Mills service, path, "org.freedesktop.DBus.Properties", "GetAll", 774ac6a4445SGunnar Mills "xyz.openbmc_project.Inventory.Item.PersistentMemory.Partition"); 775ac6a4445SGunnar Mills } 776ac6a4445SGunnar Mills 777ac6a4445SGunnar Mills inline void getDimmData(std::shared_ptr<AsyncResp> aResp, 778ac6a4445SGunnar Mills const std::string& dimmId) 779ac6a4445SGunnar Mills { 780ac6a4445SGunnar Mills BMCWEB_LOG_DEBUG << "Get available system dimm resources."; 781ac6a4445SGunnar Mills crow::connections::systemBus->async_method_call( 782ac6a4445SGunnar Mills [dimmId, aResp{std::move(aResp)}]( 783ac6a4445SGunnar Mills const boost::system::error_code ec, 784ac6a4445SGunnar Mills const boost::container::flat_map< 785ac6a4445SGunnar Mills std::string, boost::container::flat_map< 786ac6a4445SGunnar Mills std::string, std::vector<std::string>>>& 787ac6a4445SGunnar Mills subtree) { 788ac6a4445SGunnar Mills if (ec) 789ac6a4445SGunnar Mills { 790ac6a4445SGunnar Mills BMCWEB_LOG_DEBUG << "DBUS response error"; 791ac6a4445SGunnar Mills messages::internalError(aResp->res); 792ac6a4445SGunnar Mills 793ac6a4445SGunnar Mills return; 794ac6a4445SGunnar Mills } 795ac6a4445SGunnar Mills bool found = false; 796ac6a4445SGunnar Mills for (const auto& [path, object] : subtree) 797ac6a4445SGunnar Mills { 798ac6a4445SGunnar Mills if (path.find(dimmId) != std::string::npos) 799ac6a4445SGunnar Mills { 800ac6a4445SGunnar Mills for (const auto& [service, interfaces] : object) 801ac6a4445SGunnar Mills { 802ac6a4445SGunnar Mills if (!found && 803ac6a4445SGunnar Mills (std::find( 804ac6a4445SGunnar Mills interfaces.begin(), interfaces.end(), 805ac6a4445SGunnar Mills "xyz.openbmc_project.Inventory.Item.Dimm") != 806ac6a4445SGunnar Mills interfaces.end())) 807ac6a4445SGunnar Mills { 808ac6a4445SGunnar Mills getDimmDataByService(aResp, dimmId, service, path); 809ac6a4445SGunnar Mills found = true; 810ac6a4445SGunnar Mills } 811ac6a4445SGunnar Mills 812ac6a4445SGunnar Mills // partitions are separate as there can be multiple per 813ac6a4445SGunnar Mills // device, i.e. 814ac6a4445SGunnar Mills // /xyz/openbmc_project/Inventory/Item/Dimm1/Partition1 815ac6a4445SGunnar Mills // /xyz/openbmc_project/Inventory/Item/Dimm1/Partition2 816ac6a4445SGunnar Mills if (std::find(interfaces.begin(), interfaces.end(), 817ac6a4445SGunnar Mills "xyz.openbmc_project.Inventory.Item." 818ac6a4445SGunnar Mills "PersistentMemory.Partition") != 819ac6a4445SGunnar Mills interfaces.end()) 820ac6a4445SGunnar Mills { 821ac6a4445SGunnar Mills getDimmPartitionData(aResp, service, path); 822ac6a4445SGunnar Mills } 823ac6a4445SGunnar Mills } 824ac6a4445SGunnar Mills } 825ac6a4445SGunnar Mills } 826ac6a4445SGunnar Mills // Object not found 827ac6a4445SGunnar Mills if (!found) 828ac6a4445SGunnar Mills { 829ac6a4445SGunnar Mills messages::resourceNotFound(aResp->res, "Memory", dimmId); 830ac6a4445SGunnar Mills } 831ac6a4445SGunnar Mills return; 832ac6a4445SGunnar Mills }, 833ac6a4445SGunnar Mills "xyz.openbmc_project.ObjectMapper", 834ac6a4445SGunnar Mills "/xyz/openbmc_project/object_mapper", 835ac6a4445SGunnar Mills "xyz.openbmc_project.ObjectMapper", "GetSubTree", 836ac6a4445SGunnar Mills "/xyz/openbmc_project/inventory", 0, 837ac6a4445SGunnar Mills std::array<const char*, 2>{ 838ac6a4445SGunnar Mills "xyz.openbmc_project.Inventory.Item.Dimm", 839ac6a4445SGunnar Mills "xyz.openbmc_project.Inventory.Item.PersistentMemory.Partition"}); 840ac6a4445SGunnar Mills } 841ac6a4445SGunnar Mills 842ac6a4445SGunnar Mills class MemoryCollection : public Node 843ac6a4445SGunnar Mills { 844ac6a4445SGunnar Mills public: 845ac6a4445SGunnar Mills /* 846ac6a4445SGunnar Mills * Default Constructor 847ac6a4445SGunnar Mills */ 848ac6a4445SGunnar Mills MemoryCollection(App& app) : Node(app, "/redfish/v1/Systems/system/Memory/") 849ac6a4445SGunnar Mills { 850ac6a4445SGunnar Mills entityPrivileges = { 851ac6a4445SGunnar Mills {boost::beast::http::verb::get, {{"Login"}}}, 852ac6a4445SGunnar Mills {boost::beast::http::verb::head, {{"Login"}}}, 853ac6a4445SGunnar Mills {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 854ac6a4445SGunnar Mills {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 855ac6a4445SGunnar Mills {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 856ac6a4445SGunnar Mills {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 857ac6a4445SGunnar Mills } 858ac6a4445SGunnar Mills 859ac6a4445SGunnar Mills private: 860ac6a4445SGunnar Mills /** 861ac6a4445SGunnar Mills * Functions triggers appropriate requests on DBus 862ac6a4445SGunnar Mills */ 863ac6a4445SGunnar Mills void doGet(crow::Response& res, const crow::Request&, 864ac6a4445SGunnar Mills const std::vector<std::string>&) override 865ac6a4445SGunnar Mills { 866ac6a4445SGunnar Mills res.jsonValue["@odata.type"] = "#MemoryCollection.MemoryCollection"; 867ac6a4445SGunnar Mills res.jsonValue["Name"] = "Memory Module Collection"; 868ac6a4445SGunnar Mills res.jsonValue["@odata.id"] = "/redfish/v1/Systems/system/Memory"; 869ac6a4445SGunnar Mills auto asyncResp = std::make_shared<AsyncResp>(res); 870ac6a4445SGunnar Mills 87105030b8eSGunnar Mills collection_util::getCollectionMembers( 87205030b8eSGunnar Mills asyncResp, "/redfish/v1/Systems/system/Memory", 87305030b8eSGunnar Mills {"xyz.openbmc_project.Inventory.Item.Dimm"}); 874ac6a4445SGunnar Mills } 875ac6a4445SGunnar Mills }; 876ac6a4445SGunnar Mills 877ac6a4445SGunnar Mills class Memory : public Node 878ac6a4445SGunnar Mills { 879ac6a4445SGunnar Mills public: 880ac6a4445SGunnar Mills /* 881ac6a4445SGunnar Mills * Default Constructor 882ac6a4445SGunnar Mills */ 883ac6a4445SGunnar Mills Memory(App& app) : 884ac6a4445SGunnar Mills Node(app, "/redfish/v1/Systems/system/Memory/<str>/", std::string()) 885ac6a4445SGunnar Mills { 886ac6a4445SGunnar Mills entityPrivileges = { 887ac6a4445SGunnar Mills {boost::beast::http::verb::get, {{"Login"}}}, 888ac6a4445SGunnar Mills {boost::beast::http::verb::head, {{"Login"}}}, 889ac6a4445SGunnar Mills {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 890ac6a4445SGunnar Mills {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 891ac6a4445SGunnar Mills {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 892ac6a4445SGunnar Mills {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 893ac6a4445SGunnar Mills } 894ac6a4445SGunnar Mills 895ac6a4445SGunnar Mills private: 896ac6a4445SGunnar Mills /** 897ac6a4445SGunnar Mills * Functions triggers appropriate requests on DBus 898ac6a4445SGunnar Mills */ 899ac6a4445SGunnar Mills void doGet(crow::Response& res, const crow::Request&, 900ac6a4445SGunnar Mills const std::vector<std::string>& params) override 901ac6a4445SGunnar Mills { 902ac6a4445SGunnar Mills // Check if there is required param, truly entering this shall be 903ac6a4445SGunnar Mills // impossible 904ac6a4445SGunnar Mills if (params.size() != 1) 905ac6a4445SGunnar Mills { 906ac6a4445SGunnar Mills messages::internalError(res); 907ac6a4445SGunnar Mills res.end(); 908ac6a4445SGunnar Mills return; 909ac6a4445SGunnar Mills } 910ac6a4445SGunnar Mills const std::string& dimmId = params[0]; 911ac6a4445SGunnar Mills 912ac6a4445SGunnar Mills res.jsonValue["@odata.type"] = "#Memory.v1_7_0.Memory"; 913ac6a4445SGunnar Mills res.jsonValue["@odata.id"] = 914ac6a4445SGunnar Mills "/redfish/v1/Systems/system/Memory/" + dimmId; 915ac6a4445SGunnar Mills auto asyncResp = std::make_shared<AsyncResp>(res); 916ac6a4445SGunnar Mills 917ac6a4445SGunnar Mills getDimmData(asyncResp, dimmId); 918ac6a4445SGunnar Mills } 919ac6a4445SGunnar Mills }; 920ac6a4445SGunnar Mills 921ac6a4445SGunnar Mills } // namespace redfish 922