1eee0013eSWilly Tu #pragma once 23ccb3adbSEd Tanous #include "async_resp.hpp" 33ccb3adbSEd Tanous #include "dbus_utility.hpp" 43ccb3adbSEd Tanous #include "error_messages.hpp" 53ccb3adbSEd Tanous #include "generated/enums/resource.hpp" 6eddfc437SWilly Tu #include "http/utility.hpp" 73ccb3adbSEd Tanous #include "utils/dbus_utils.hpp" 83ccb3adbSEd Tanous 9e99073f5SGeorge Liu #include <boost/system/error_code.hpp> 10ef4c65b7SEd Tanous #include <boost/url/format.hpp> 11eee0013eSWilly Tu #include <sdbusplus/asio/property.hpp> 12d1bde9e5SKrzysztof Grobelny #include <sdbusplus/unpack_properties.hpp> 13eee0013eSWilly Tu 14eee0013eSWilly Tu #include <algorithm> 15e99073f5SGeorge Liu #include <array> 167f23576aSJagpal Singh Gill #include <optional> 173544d2a7SEd Tanous #include <ranges> 18eee0013eSWilly Tu #include <string> 19e99073f5SGeorge Liu #include <string_view> 20eee0013eSWilly Tu #include <vector> 21eee0013eSWilly Tu 22eee0013eSWilly Tu namespace redfish 23eee0013eSWilly Tu { 24eee0013eSWilly Tu namespace sw_util 25eee0013eSWilly Tu { 26eee0013eSWilly Tu /* @brief String that indicates a bios software instance */ 27eee0013eSWilly Tu constexpr const char* biosPurpose = 28eee0013eSWilly Tu "xyz.openbmc_project.Software.Version.VersionPurpose.Host"; 29eee0013eSWilly Tu 30eee0013eSWilly Tu /* @brief String that indicates a BMC software instance */ 31eee0013eSWilly Tu constexpr const char* bmcPurpose = 32eee0013eSWilly Tu "xyz.openbmc_project.Software.Version.VersionPurpose.BMC"; 33eee0013eSWilly Tu 347f23576aSJagpal Singh Gill inline std::optional<sdbusplus::message::object_path> 357f23576aSJagpal Singh Gill getFunctionalSoftwarePath(const std::string& swType) 367f23576aSJagpal Singh Gill { 377f23576aSJagpal Singh Gill if (swType == bmcPurpose) 387f23576aSJagpal Singh Gill { 397f23576aSJagpal Singh Gill if constexpr (BMCWEB_REDFISH_UPDATESERVICE_USE_DBUS) 407f23576aSJagpal Singh Gill { 417f23576aSJagpal Singh Gill return sdbusplus::message::object_path( 427f23576aSJagpal Singh Gill "/xyz/openbmc_project/software/bmc/functional"); 437f23576aSJagpal Singh Gill } 447f23576aSJagpal Singh Gill else 457f23576aSJagpal Singh Gill { 467f23576aSJagpal Singh Gill return sdbusplus::message::object_path( 477f23576aSJagpal Singh Gill "/xyz/openbmc_project/software/functional"); 487f23576aSJagpal Singh Gill } 497f23576aSJagpal Singh Gill } 507f23576aSJagpal Singh Gill else if (swType == biosPurpose) 517f23576aSJagpal Singh Gill { 527f23576aSJagpal Singh Gill if constexpr (BMCWEB_REDFISH_UPDATESERVICE_USE_DBUS) 537f23576aSJagpal Singh Gill { 547f23576aSJagpal Singh Gill return sdbusplus::message::object_path( 557f23576aSJagpal Singh Gill "/xyz/openbmc_project/software/bios/functional"); 567f23576aSJagpal Singh Gill } 577f23576aSJagpal Singh Gill else 587f23576aSJagpal Singh Gill { 597f23576aSJagpal Singh Gill return sdbusplus::message::object_path( 607f23576aSJagpal Singh Gill "/xyz/openbmc_project/software/functional"); 617f23576aSJagpal Singh Gill } 627f23576aSJagpal Singh Gill } 637f23576aSJagpal Singh Gill else 647f23576aSJagpal Singh Gill { 657f23576aSJagpal Singh Gill BMCWEB_LOG_ERROR("No valid software path"); 667f23576aSJagpal Singh Gill return std::nullopt; 677f23576aSJagpal Singh Gill } 687f23576aSJagpal Singh Gill } 697f23576aSJagpal Singh Gill 70f8010a3dSEd Tanous inline void afterGetProperties( 71f8010a3dSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 72f8010a3dSEd Tanous const std::string& swId, bool runningImage, 73f8010a3dSEd Tanous const std::string& swVersionPurpose, 74f8010a3dSEd Tanous const std::string& activeVersionPropName, bool populateLinkToImages, 75f8010a3dSEd Tanous const boost::system::error_code& ec, 76f8010a3dSEd Tanous const dbus::utility::DBusPropertiesMap& propertiesList) 77f8010a3dSEd Tanous { 78f8010a3dSEd Tanous if (ec) 79f8010a3dSEd Tanous { 80f8010a3dSEd Tanous BMCWEB_LOG_ERROR("error_code = {}", ec); 81f8010a3dSEd Tanous BMCWEB_LOG_ERROR("error msg = {}", ec.message()); 82f8010a3dSEd Tanous // Have seen the code update app delete the 83f8010a3dSEd Tanous // D-Bus object, during code update, between 84f8010a3dSEd Tanous // the call to mapper and here. Just leave 85f8010a3dSEd Tanous // these properties off if resource not 86f8010a3dSEd Tanous // found. 87f8010a3dSEd Tanous if (ec.value() == EBADR) 88f8010a3dSEd Tanous { 89f8010a3dSEd Tanous return; 90f8010a3dSEd Tanous } 91f8010a3dSEd Tanous messages::internalError(asyncResp->res); 92f8010a3dSEd Tanous return; 93f8010a3dSEd Tanous } 94f8010a3dSEd Tanous // example propertiesList 95f8010a3dSEd Tanous // a{sv} 2 "Version" s 96f8010a3dSEd Tanous // "IBM-witherspoon-OP9-v2.0.10-2.22" "Purpose" 97f8010a3dSEd Tanous // s 98f8010a3dSEd Tanous // "xyz.openbmc_project.Software.Version.VersionPurpose.Host" 99f8010a3dSEd Tanous const std::string* version = nullptr; 100f8010a3dSEd Tanous const std::string* swInvPurpose = nullptr; 101f8010a3dSEd Tanous 102f8010a3dSEd Tanous const bool success = sdbusplus::unpackPropertiesNoThrow( 103f8010a3dSEd Tanous dbus_utils::UnpackErrorPrinter(), propertiesList, "Purpose", 104f8010a3dSEd Tanous swInvPurpose, "Version", version); 105f8010a3dSEd Tanous 106f8010a3dSEd Tanous if (!success) 107f8010a3dSEd Tanous { 108f8010a3dSEd Tanous messages::internalError(asyncResp->res); 109f8010a3dSEd Tanous return; 110f8010a3dSEd Tanous } 111f8010a3dSEd Tanous 112f8010a3dSEd Tanous if (version == nullptr || version->empty()) 113f8010a3dSEd Tanous { 114f8010a3dSEd Tanous messages::internalError(asyncResp->res); 115f8010a3dSEd Tanous return; 116f8010a3dSEd Tanous } 117f8010a3dSEd Tanous if (swInvPurpose == nullptr || *swInvPurpose != swVersionPurpose) 118f8010a3dSEd Tanous { 119f8010a3dSEd Tanous // Not purpose we're looking for 120f8010a3dSEd Tanous return; 121f8010a3dSEd Tanous } 122f8010a3dSEd Tanous 123f8010a3dSEd Tanous BMCWEB_LOG_DEBUG("Image ID: {}", swId); 124f8010a3dSEd Tanous BMCWEB_LOG_DEBUG("Running image: {}", runningImage); 125f8010a3dSEd Tanous BMCWEB_LOG_DEBUG("Image purpose: {}", *swInvPurpose); 126f8010a3dSEd Tanous 127f8010a3dSEd Tanous if (populateLinkToImages) 128f8010a3dSEd Tanous { 129f8010a3dSEd Tanous nlohmann::json& softwareImageMembers = 130f8010a3dSEd Tanous asyncResp->res.jsonValue["Links"]["SoftwareImages"]; 131f8010a3dSEd Tanous // Firmware images are at 132f8010a3dSEd Tanous // /redfish/v1/UpdateService/FirmwareInventory/<Id> 133f8010a3dSEd Tanous // e.g. .../FirmwareInventory/82d3ec86 134f8010a3dSEd Tanous nlohmann::json::object_t member; 135f8010a3dSEd Tanous member["@odata.id"] = boost::urls::format( 136f8010a3dSEd Tanous "/redfish/v1/UpdateService/FirmwareInventory/{}", swId); 137f8010a3dSEd Tanous softwareImageMembers.emplace_back(std::move(member)); 138f8010a3dSEd Tanous asyncResp->res.jsonValue["Links"]["SoftwareImages@odata.count"] = 139f8010a3dSEd Tanous softwareImageMembers.size(); 140f8010a3dSEd Tanous 141f8010a3dSEd Tanous if (runningImage) 142f8010a3dSEd Tanous { 143f8010a3dSEd Tanous nlohmann::json::object_t runningMember; 144f8010a3dSEd Tanous runningMember["@odata.id"] = boost::urls::format( 145f8010a3dSEd Tanous "/redfish/v1/UpdateService/FirmwareInventory/{}", swId); 146f8010a3dSEd Tanous // Create the link to the running image 147f8010a3dSEd Tanous asyncResp->res.jsonValue["Links"]["ActiveSoftwareImage"] = 148f8010a3dSEd Tanous std::move(runningMember); 149f8010a3dSEd Tanous } 150f8010a3dSEd Tanous } 151f8010a3dSEd Tanous if (!activeVersionPropName.empty() && runningImage) 152f8010a3dSEd Tanous { 153f8010a3dSEd Tanous asyncResp->res.jsonValue[activeVersionPropName] = *version; 154f8010a3dSEd Tanous } 155f8010a3dSEd Tanous } 156f8010a3dSEd Tanous 157f8010a3dSEd Tanous inline void afterGetSubtree( 158f8010a3dSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 159f8010a3dSEd Tanous const std::string& swVersionPurpose, 160f8010a3dSEd Tanous const std::string& activeVersionPropName, bool populateLinkToImages, 161f8010a3dSEd Tanous const std::vector<std::string>& functionalSwIds, 162f8010a3dSEd Tanous const boost::system::error_code& ec, 163f8010a3dSEd Tanous const dbus::utility::MapperGetSubTreeResponse& subtree) 164f8010a3dSEd Tanous { 165f8010a3dSEd Tanous if (ec) 166f8010a3dSEd Tanous { 167f8010a3dSEd Tanous BMCWEB_LOG_ERROR("error_code = {}", ec); 168f8010a3dSEd Tanous BMCWEB_LOG_ERROR("error msg = {}", ec.message()); 169f8010a3dSEd Tanous messages::internalError(asyncResp->res); 170f8010a3dSEd Tanous return; 171f8010a3dSEd Tanous } 172f8010a3dSEd Tanous 173f8010a3dSEd Tanous BMCWEB_LOG_DEBUG("Found {} images", subtree.size()); 174f8010a3dSEd Tanous 175f8010a3dSEd Tanous for (const std::pair< 176f8010a3dSEd Tanous std::string, 177f8010a3dSEd Tanous std::vector<std::pair<std::string, std::vector<std::string>>>>& 178f8010a3dSEd Tanous obj : subtree) 179f8010a3dSEd Tanous { 180f8010a3dSEd Tanous sdbusplus::message::object_path path(obj.first); 181f8010a3dSEd Tanous std::string swId = path.filename(); 182f8010a3dSEd Tanous if (swId.empty()) 183f8010a3dSEd Tanous { 184f8010a3dSEd Tanous messages::internalError(asyncResp->res); 185f8010a3dSEd Tanous BMCWEB_LOG_ERROR("Invalid software ID"); 186f8010a3dSEd Tanous 187f8010a3dSEd Tanous return; 188f8010a3dSEd Tanous } 189f8010a3dSEd Tanous 190f8010a3dSEd Tanous bool runningImage = false; 191f8010a3dSEd Tanous // Look at Ids from 192f8010a3dSEd Tanous // /xyz/openbmc_project/software/functional 193f8010a3dSEd Tanous // to determine if this is 194f8010a3dSEd Tanous // a running image 195f8010a3dSEd Tanous if (std::ranges::find(functionalSwIds, swId) != functionalSwIds.end()) 196f8010a3dSEd Tanous { 197f8010a3dSEd Tanous runningImage = true; 198f8010a3dSEd Tanous } 199f8010a3dSEd Tanous 200f8010a3dSEd Tanous // Now grab its version 201f8010a3dSEd Tanous // info 202deae6a78SEd Tanous dbus::utility::getAllProperties( 203f8010a3dSEd Tanous *crow::connections::systemBus, obj.second[0].first, obj.first, 204f8010a3dSEd Tanous "xyz.openbmc_project.Software.Version", 205f8010a3dSEd Tanous [asyncResp, swId, runningImage, swVersionPurpose, 206f8010a3dSEd Tanous activeVersionPropName, populateLinkToImages]( 207f8010a3dSEd Tanous const boost::system::error_code& ec3, 208f8010a3dSEd Tanous const dbus::utility::DBusPropertiesMap& propertiesList) { 209f8010a3dSEd Tanous afterGetProperties(asyncResp, swId, runningImage, 210f8010a3dSEd Tanous swVersionPurpose, activeVersionPropName, 211f8010a3dSEd Tanous populateLinkToImages, ec3, propertiesList); 212f8010a3dSEd Tanous }); 213f8010a3dSEd Tanous } 214f8010a3dSEd Tanous } 215f8010a3dSEd Tanous 216f8010a3dSEd Tanous inline void afterAssociatedEndpoints( 217f8010a3dSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 218f8010a3dSEd Tanous const std::string& swVersionPurpose, 219f8010a3dSEd Tanous const std::string& activeVersionPropName, bool populateLinkToImages, 220f8010a3dSEd Tanous const boost::system::error_code& ec, 221f8010a3dSEd Tanous const dbus::utility::MapperEndPoints& functionalSw) 222f8010a3dSEd Tanous { 223f8010a3dSEd Tanous BMCWEB_LOG_DEBUG("populateSoftwareInformation enter"); 224f8010a3dSEd Tanous if (ec) 225f8010a3dSEd Tanous { 226*a5f87d48SGunnar Mills BMCWEB_LOG_DEBUG("error_code = {}", ec); 227*a5f87d48SGunnar Mills BMCWEB_LOG_DEBUG("error msg = {}", ec.message()); 228f8010a3dSEd Tanous // No functional software for this swVersionPurpose, so just 229f8010a3dSEd Tanous return; 230f8010a3dSEd Tanous } 231f8010a3dSEd Tanous 232f8010a3dSEd Tanous if (functionalSw.empty()) 233f8010a3dSEd Tanous { 234f8010a3dSEd Tanous // Could keep going and try to populate SoftwareImages 235f8010a3dSEd Tanous // but something is seriously wrong, so just fail 236f8010a3dSEd Tanous BMCWEB_LOG_ERROR("Zero functional software in system"); 237f8010a3dSEd Tanous messages::internalError(asyncResp->res); 238f8010a3dSEd Tanous return; 239f8010a3dSEd Tanous } 240f8010a3dSEd Tanous 241f8010a3dSEd Tanous std::vector<std::string> functionalSwIds; 242f8010a3dSEd Tanous // example functionalSw: 243f8010a3dSEd Tanous // v as 2 "/xyz/openbmc_project/software/ace821ef" 244f8010a3dSEd Tanous // "/xyz/openbmc_project/software/230fb078" 245f8010a3dSEd Tanous for (const auto& sw : functionalSw) 246f8010a3dSEd Tanous { 247f8010a3dSEd Tanous sdbusplus::message::object_path path(sw); 248f8010a3dSEd Tanous std::string leaf = path.filename(); 249f8010a3dSEd Tanous if (leaf.empty()) 250f8010a3dSEd Tanous { 251f8010a3dSEd Tanous continue; 252f8010a3dSEd Tanous } 253f8010a3dSEd Tanous 254f8010a3dSEd Tanous functionalSwIds.push_back(leaf); 255f8010a3dSEd Tanous } 256f8010a3dSEd Tanous 257f8010a3dSEd Tanous constexpr std::array<std::string_view, 1> interfaces = { 258f8010a3dSEd Tanous "xyz.openbmc_project.Software.Version"}; 259f8010a3dSEd Tanous dbus::utility::getSubTree( 260f8010a3dSEd Tanous "/xyz/openbmc_project/software", 0, interfaces, 261f8010a3dSEd Tanous [asyncResp, swVersionPurpose, activeVersionPropName, 262f8010a3dSEd Tanous populateLinkToImages, functionalSwIds]( 263f8010a3dSEd Tanous const boost::system::error_code& ec2, 264f8010a3dSEd Tanous const dbus::utility::MapperGetSubTreeResponse& subtree) { 265f8010a3dSEd Tanous afterGetSubtree(asyncResp, swVersionPurpose, activeVersionPropName, 266f8010a3dSEd Tanous populateLinkToImages, functionalSwIds, ec2, 267f8010a3dSEd Tanous subtree); 268f8010a3dSEd Tanous }); 269f8010a3dSEd Tanous } 270f8010a3dSEd Tanous 271eee0013eSWilly Tu /** 272eee0013eSWilly Tu * @brief Populate the running software version and image links 273eee0013eSWilly Tu * 274ac106bf6SEd Tanous * @param[i,o] asyncResp Async response object 275eee0013eSWilly Tu * @param[i] swVersionPurpose Indicates what target to look for 276ac106bf6SEd Tanous * @param[i] activeVersionPropName Index in asyncResp->res.jsonValue to write 277eee0013eSWilly Tu * the running software version to 278ac106bf6SEd Tanous * @param[i] populateLinkToImages Populate asyncResp->res "Links" 279eee0013eSWilly Tu * "ActiveSoftwareImage" with a link to the running software image and 280eee0013eSWilly Tu * "SoftwareImages" with a link to the all its software images 281eee0013eSWilly Tu * 282eee0013eSWilly Tu * @return void 283eee0013eSWilly Tu */ 284ac106bf6SEd Tanous inline void populateSoftwareInformation( 285ac106bf6SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 286eee0013eSWilly Tu const std::string& swVersionPurpose, 287ac106bf6SEd Tanous const std::string& activeVersionPropName, const bool populateLinkToImages) 288eee0013eSWilly Tu { 2897f23576aSJagpal Singh Gill auto swPath = getFunctionalSoftwarePath(swVersionPurpose); 2907f23576aSJagpal Singh Gill if (!swPath) 2917f23576aSJagpal Singh Gill { 2927f23576aSJagpal Singh Gill BMCWEB_LOG_ERROR("Invalid software type"); 2937f23576aSJagpal Singh Gill messages::internalError(asyncResp->res); 2947f23576aSJagpal Singh Gill return; 2957f23576aSJagpal Singh Gill } 296eee0013eSWilly Tu // Used later to determine running (known on Redfish as active) Sw images 297a4eb761aSGeorge Liu dbus::utility::getAssociationEndPoints( 2987f23576aSJagpal Singh Gill swPath.value().str, 299ac106bf6SEd Tanous [asyncResp, swVersionPurpose, activeVersionPropName, 300ac106bf6SEd Tanous populateLinkToImages]( 301a4eb761aSGeorge Liu const boost::system::error_code& ec, 302a4eb761aSGeorge Liu const dbus::utility::MapperEndPoints& functionalSw) { 303f8010a3dSEd Tanous afterAssociatedEndpoints(asyncResp, swVersionPurpose, 304f8010a3dSEd Tanous activeVersionPropName, 305f8010a3dSEd Tanous populateLinkToImages, ec, functionalSw); 306eee0013eSWilly Tu }); 307eee0013eSWilly Tu } 308eee0013eSWilly Tu 309eee0013eSWilly Tu /** 310eee0013eSWilly Tu * @brief Translate input swState to Redfish state 311eee0013eSWilly Tu * 312eee0013eSWilly Tu * This function will return the corresponding Redfish state 313eee0013eSWilly Tu * 314eee0013eSWilly Tu * @param[i] swState The OpenBMC software state 315eee0013eSWilly Tu * 316eee0013eSWilly Tu * @return The corresponding Redfish state 317eee0013eSWilly Tu */ 3180ec8b83dSEd Tanous inline resource::State getRedfishSwState(const std::string& swState) 319eee0013eSWilly Tu { 320eee0013eSWilly Tu if (swState == "xyz.openbmc_project.Software.Activation.Activations.Active") 321eee0013eSWilly Tu { 3220ec8b83dSEd Tanous return resource::State::Enabled; 323eee0013eSWilly Tu } 324eee0013eSWilly Tu if (swState == "xyz.openbmc_project.Software.Activation." 325eee0013eSWilly Tu "Activations.Activating") 326eee0013eSWilly Tu { 3270ec8b83dSEd Tanous return resource::State::Updating; 328eee0013eSWilly Tu } 329eee0013eSWilly Tu if (swState == "xyz.openbmc_project.Software.Activation." 330eee0013eSWilly Tu "Activations.StandbySpare") 331eee0013eSWilly Tu { 3320ec8b83dSEd Tanous return resource::State::StandbySpare; 333eee0013eSWilly Tu } 33462598e31SEd Tanous BMCWEB_LOG_DEBUG("Default sw state {} to Disabled", swState); 3350ec8b83dSEd Tanous return resource::State::Disabled; 336eee0013eSWilly Tu } 337eee0013eSWilly Tu 338eee0013eSWilly Tu /** 339eee0013eSWilly Tu * @brief Translate input swState to Redfish health state 340eee0013eSWilly Tu * 341eee0013eSWilly Tu * This function will return the corresponding Redfish health state 342eee0013eSWilly Tu * 343eee0013eSWilly Tu * @param[i] swState The OpenBMC software state 344eee0013eSWilly Tu * 345eee0013eSWilly Tu * @return The corresponding Redfish health state 346eee0013eSWilly Tu */ 347eee0013eSWilly Tu inline std::string getRedfishSwHealth(const std::string& swState) 348eee0013eSWilly Tu { 349eee0013eSWilly Tu if ((swState == 350eee0013eSWilly Tu "xyz.openbmc_project.Software.Activation.Activations.Active") || 351eee0013eSWilly Tu (swState == "xyz.openbmc_project.Software.Activation.Activations." 352eee0013eSWilly Tu "Activating") || 353eee0013eSWilly Tu (swState == 354eee0013eSWilly Tu "xyz.openbmc_project.Software.Activation.Activations.Ready")) 355eee0013eSWilly Tu { 356eee0013eSWilly Tu return "OK"; 357eee0013eSWilly Tu } 35862598e31SEd Tanous BMCWEB_LOG_DEBUG("Sw state {} to Warning", swState); 359eee0013eSWilly Tu return "Warning"; 360eee0013eSWilly Tu } 361eee0013eSWilly Tu 362eee0013eSWilly Tu /** 363eee0013eSWilly Tu * @brief Put status of input swId into json response 364eee0013eSWilly Tu * 365eee0013eSWilly Tu * This function will put the appropriate Redfish state of the input 366eee0013eSWilly Tu * software id to ["Status"]["State"] within the json response 367eee0013eSWilly Tu * 368ac106bf6SEd Tanous * @param[i,o] asyncResp Async response object 369eee0013eSWilly Tu * @param[i] swId The software ID to get status for 370eee0013eSWilly Tu * @param[i] dbusSvc The dbus service implementing the software object 371eee0013eSWilly Tu * 372eee0013eSWilly Tu * @return void 373eee0013eSWilly Tu */ 374eee0013eSWilly Tu inline void getSwStatus(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 375eee0013eSWilly Tu const std::shared_ptr<std::string>& swId, 376eee0013eSWilly Tu const std::string& dbusSvc) 377eee0013eSWilly Tu { 37862598e31SEd Tanous BMCWEB_LOG_DEBUG("getSwStatus: swId {} svc {}", *swId, dbusSvc); 379eee0013eSWilly Tu 380deae6a78SEd Tanous dbus::utility::getAllProperties( 381deae6a78SEd Tanous dbusSvc, "/xyz/openbmc_project/software/" + *swId, 382d1bde9e5SKrzysztof Grobelny "xyz.openbmc_project.Software.Activation", 383eee0013eSWilly Tu [asyncResp, 3848b24275dSEd Tanous swId](const boost::system::error_code& ec, 385eee0013eSWilly Tu const dbus::utility::DBusPropertiesMap& propertiesList) { 3868b24275dSEd Tanous if (ec) 387eee0013eSWilly Tu { 388eee0013eSWilly Tu // not all swtypes are updateable, this is ok 389539d8c6bSEd Tanous asyncResp->res.jsonValue["Status"]["State"] = 390539d8c6bSEd Tanous resource::State::Enabled; 391eee0013eSWilly Tu return; 392eee0013eSWilly Tu } 393d1bde9e5SKrzysztof Grobelny 394eee0013eSWilly Tu const std::string* swInvActivation = nullptr; 395d1bde9e5SKrzysztof Grobelny 396d1bde9e5SKrzysztof Grobelny const bool success = sdbusplus::unpackPropertiesNoThrow( 397d1bde9e5SKrzysztof Grobelny dbus_utils::UnpackErrorPrinter(), propertiesList, "Activation", 398d1bde9e5SKrzysztof Grobelny swInvActivation); 399d1bde9e5SKrzysztof Grobelny 400d1bde9e5SKrzysztof Grobelny if (!success) 401eee0013eSWilly Tu { 402d1bde9e5SKrzysztof Grobelny messages::internalError(asyncResp->res); 403d1bde9e5SKrzysztof Grobelny return; 404eee0013eSWilly Tu } 405eee0013eSWilly Tu 406eee0013eSWilly Tu if (swInvActivation == nullptr) 407eee0013eSWilly Tu { 408eee0013eSWilly Tu messages::internalError(asyncResp->res); 409eee0013eSWilly Tu return; 410eee0013eSWilly Tu } 411d1bde9e5SKrzysztof Grobelny 41262598e31SEd Tanous BMCWEB_LOG_DEBUG("getSwStatus: Activation {}", *swInvActivation); 413eee0013eSWilly Tu asyncResp->res.jsonValue["Status"]["State"] = 414eee0013eSWilly Tu getRedfishSwState(*swInvActivation); 415eee0013eSWilly Tu asyncResp->res.jsonValue["Status"]["Health"] = 416eee0013eSWilly Tu getRedfishSwHealth(*swInvActivation); 417d1bde9e5SKrzysztof Grobelny }); 418eee0013eSWilly Tu } 419eee0013eSWilly Tu 420c018f705SJagpal Singh Gill inline void handleUpdateableEndpoints( 421c018f705SJagpal Singh Gill const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 422c018f705SJagpal Singh Gill const std::shared_ptr<std::string>& swId, 423c018f705SJagpal Singh Gill const boost::system::error_code& ec, 424c018f705SJagpal Singh Gill const dbus::utility::MapperEndPoints& objPaths) 425c018f705SJagpal Singh Gill { 426c018f705SJagpal Singh Gill if (ec) 427c018f705SJagpal Singh Gill { 428c018f705SJagpal Singh Gill BMCWEB_LOG_DEBUG(" error_code = {} error msg = {}", ec, ec.message()); 429c018f705SJagpal Singh Gill // System can exist with no updateable software, 430c018f705SJagpal Singh Gill // so don't throw error here. 431c018f705SJagpal Singh Gill return; 432c018f705SJagpal Singh Gill } 433c018f705SJagpal Singh Gill sdbusplus::message::object_path reqSwObjPath( 434c018f705SJagpal Singh Gill "/xyz/openbmc_project/software"); 435c018f705SJagpal Singh Gill reqSwObjPath = reqSwObjPath / *swId; 436c018f705SJagpal Singh Gill 437c018f705SJagpal Singh Gill if (std::ranges::find(objPaths, reqSwObjPath.str) != objPaths.end()) 438c018f705SJagpal Singh Gill { 439c018f705SJagpal Singh Gill asyncResp->res.jsonValue["Updateable"] = true; 440c018f705SJagpal Singh Gill return; 441c018f705SJagpal Singh Gill } 442c018f705SJagpal Singh Gill } 443c018f705SJagpal Singh Gill 444c018f705SJagpal Singh Gill inline void 445c018f705SJagpal Singh Gill handleUpdateableObject(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 446c018f705SJagpal Singh Gill const boost::system::error_code& ec, 447c018f705SJagpal Singh Gill const dbus::utility::MapperGetObject& objectInfo) 448c018f705SJagpal Singh Gill { 449c018f705SJagpal Singh Gill if (ec) 450c018f705SJagpal Singh Gill { 451c018f705SJagpal Singh Gill BMCWEB_LOG_DEBUG(" error_code = {} error msg = {}", ec, ec.message()); 452c018f705SJagpal Singh Gill // System can exist with no updateable software, 453c018f705SJagpal Singh Gill // so don't throw error here. 454c018f705SJagpal Singh Gill return; 455c018f705SJagpal Singh Gill } 456c018f705SJagpal Singh Gill if (objectInfo.empty()) 457c018f705SJagpal Singh Gill { 458c018f705SJagpal Singh Gill BMCWEB_LOG_DEBUG("No updateable software found"); 459c018f705SJagpal Singh Gill // System can exist with no updateable software, 460c018f705SJagpal Singh Gill // so don't throw error here. 461c018f705SJagpal Singh Gill return; 462c018f705SJagpal Singh Gill } 463c018f705SJagpal Singh Gill asyncResp->res.jsonValue["Updateable"] = true; 464c018f705SJagpal Singh Gill } 465c018f705SJagpal Singh Gill 466eee0013eSWilly Tu /** 467eee0013eSWilly Tu * @brief Updates programmable status of input swId into json response 468eee0013eSWilly Tu * 469eee0013eSWilly Tu * This function checks whether software inventory component 470eee0013eSWilly Tu * can be programmable or not and fill's the "Updatable" 471eee0013eSWilly Tu * Property. 472eee0013eSWilly Tu * 473eee0013eSWilly Tu * @param[i,o] asyncResp Async response object 474eee0013eSWilly Tu * @param[i] swId The software ID 475eee0013eSWilly Tu */ 476eee0013eSWilly Tu inline void 477eee0013eSWilly Tu getSwUpdatableStatus(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 478eee0013eSWilly Tu const std::shared_ptr<std::string>& swId) 479eee0013eSWilly Tu { 480c018f705SJagpal Singh Gill if constexpr (BMCWEB_REDFISH_UPDATESERVICE_USE_DBUS) 481c018f705SJagpal Singh Gill { 482c018f705SJagpal Singh Gill sdbusplus::message::object_path swObjectPath( 483c018f705SJagpal Singh Gill "/xyz/openbmc_project/software"); 484c018f705SJagpal Singh Gill swObjectPath = swObjectPath / *swId; 485c018f705SJagpal Singh Gill constexpr std::array<std::string_view, 1> interfaces = { 486c018f705SJagpal Singh Gill "xyz.openbmc_project.Software.Update"}; 487c018f705SJagpal Singh Gill dbus::utility::getDbusObject( 488c018f705SJagpal Singh Gill swObjectPath.str, interfaces, 489c018f705SJagpal Singh Gill std::bind_front(handleUpdateableObject, asyncResp)); 490c018f705SJagpal Singh Gill } 491c018f705SJagpal Singh Gill else 492c018f705SJagpal Singh Gill { 4936c3e9451SGeorge Liu dbus::utility::getAssociationEndPoints( 494eee0013eSWilly Tu "/xyz/openbmc_project/software/updateable", 495c018f705SJagpal Singh Gill std::bind_front(handleUpdateableEndpoints, asyncResp, swId)); 496eee0013eSWilly Tu } 497eee0013eSWilly Tu } 498eee0013eSWilly Tu 499eee0013eSWilly Tu } // namespace sw_util 500eee0013eSWilly Tu } // namespace redfish 501