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