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