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 70eee0013eSWilly Tu /** 71eee0013eSWilly Tu * @brief Populate the running software version and image links 72eee0013eSWilly Tu * 73ac106bf6SEd Tanous * @param[i,o] asyncResp Async response object 74eee0013eSWilly Tu * @param[i] swVersionPurpose Indicates what target to look for 75ac106bf6SEd Tanous * @param[i] activeVersionPropName Index in asyncResp->res.jsonValue to write 76eee0013eSWilly Tu * the running software version to 77ac106bf6SEd Tanous * @param[i] populateLinkToImages Populate asyncResp->res "Links" 78eee0013eSWilly Tu * "ActiveSoftwareImage" with a link to the running software image and 79eee0013eSWilly Tu * "SoftwareImages" with a link to the all its software images 80eee0013eSWilly Tu * 81eee0013eSWilly Tu * @return void 82eee0013eSWilly Tu */ 83ac106bf6SEd Tanous inline void populateSoftwareInformation( 84ac106bf6SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 85eee0013eSWilly Tu const std::string& swVersionPurpose, 86ac106bf6SEd Tanous const std::string& activeVersionPropName, const bool populateLinkToImages) 87eee0013eSWilly Tu { 887f23576aSJagpal Singh Gill auto swPath = getFunctionalSoftwarePath(swVersionPurpose); 897f23576aSJagpal Singh Gill if (!swPath) 907f23576aSJagpal Singh Gill { 917f23576aSJagpal Singh Gill BMCWEB_LOG_ERROR("Invalid software type"); 927f23576aSJagpal Singh Gill messages::internalError(asyncResp->res); 937f23576aSJagpal Singh Gill return; 947f23576aSJagpal Singh Gill } 95eee0013eSWilly Tu // Used later to determine running (known on Redfish as active) Sw images 96a4eb761aSGeorge Liu dbus::utility::getAssociationEndPoints( 977f23576aSJagpal Singh Gill swPath.value().str, 98ac106bf6SEd Tanous [asyncResp, swVersionPurpose, activeVersionPropName, 99ac106bf6SEd Tanous populateLinkToImages]( 100a4eb761aSGeorge Liu const boost::system::error_code& ec, 101a4eb761aSGeorge Liu const dbus::utility::MapperEndPoints& functionalSw) { 10262598e31SEd Tanous BMCWEB_LOG_DEBUG("populateSoftwareInformation enter"); 103eee0013eSWilly Tu if (ec) 104eee0013eSWilly Tu { 10562598e31SEd Tanous BMCWEB_LOG_ERROR("error_code = {}", ec); 10662598e31SEd Tanous BMCWEB_LOG_ERROR("error msg = {}", ec.message()); 107ac106bf6SEd Tanous messages::internalError(asyncResp->res); 108eee0013eSWilly Tu return; 109eee0013eSWilly Tu } 110eee0013eSWilly Tu 111eee0013eSWilly Tu if (functionalSw.empty()) 112eee0013eSWilly Tu { 113eee0013eSWilly Tu // Could keep going and try to populate SoftwareImages but 114eee0013eSWilly Tu // something is seriously wrong, so just fail 11562598e31SEd Tanous BMCWEB_LOG_ERROR("Zero functional software in system"); 116ac106bf6SEd Tanous messages::internalError(asyncResp->res); 117eee0013eSWilly Tu return; 118eee0013eSWilly Tu } 119eee0013eSWilly Tu 120eee0013eSWilly Tu std::vector<std::string> functionalSwIds; 121eee0013eSWilly Tu // example functionalSw: 122eee0013eSWilly Tu // v as 2 "/xyz/openbmc_project/software/ace821ef" 123eee0013eSWilly Tu // "/xyz/openbmc_project/software/230fb078" 124c6830d5fSGunnar Mills for (const auto& sw : functionalSw) 125eee0013eSWilly Tu { 126c6830d5fSGunnar Mills sdbusplus::message::object_path path(sw); 127eee0013eSWilly Tu std::string leaf = path.filename(); 128eee0013eSWilly Tu if (leaf.empty()) 129eee0013eSWilly Tu { 130eee0013eSWilly Tu continue; 131eee0013eSWilly Tu } 132eee0013eSWilly Tu 133eee0013eSWilly Tu functionalSwIds.push_back(leaf); 134eee0013eSWilly Tu } 135eee0013eSWilly Tu 136e99073f5SGeorge Liu constexpr std::array<std::string_view, 1> interfaces = { 137e99073f5SGeorge Liu "xyz.openbmc_project.Software.Version"}; 138e99073f5SGeorge Liu dbus::utility::getSubTree( 139e99073f5SGeorge Liu "/xyz/openbmc_project/software", 0, interfaces, 140ac106bf6SEd Tanous [asyncResp, swVersionPurpose, activeVersionPropName, 141eee0013eSWilly Tu populateLinkToImages, functionalSwIds]( 142e99073f5SGeorge Liu const boost::system::error_code& ec2, 143eee0013eSWilly Tu const dbus::utility::MapperGetSubTreeResponse& subtree) { 144eee0013eSWilly Tu if (ec2) 145eee0013eSWilly Tu { 14662598e31SEd Tanous BMCWEB_LOG_ERROR("error_code = {}", ec2); 14762598e31SEd Tanous BMCWEB_LOG_ERROR("error msg = {}", ec2.message()); 148ac106bf6SEd Tanous messages::internalError(asyncResp->res); 149eee0013eSWilly Tu return; 150eee0013eSWilly Tu } 151eee0013eSWilly Tu 15262598e31SEd Tanous BMCWEB_LOG_DEBUG("Found {} images", subtree.size()); 153eee0013eSWilly Tu 154eee0013eSWilly Tu for (const std::pair<std::string, 155eee0013eSWilly Tu std::vector<std::pair< 156eee0013eSWilly Tu std::string, std::vector<std::string>>>>& 157eee0013eSWilly Tu obj : subtree) 158eee0013eSWilly Tu { 159eee0013eSWilly Tu sdbusplus::message::object_path path(obj.first); 160eee0013eSWilly Tu std::string swId = path.filename(); 161eee0013eSWilly Tu if (swId.empty()) 162eee0013eSWilly Tu { 163ac106bf6SEd Tanous messages::internalError(asyncResp->res); 16462598e31SEd Tanous BMCWEB_LOG_ERROR("Invalid software ID"); 165eee0013eSWilly Tu 166eee0013eSWilly Tu return; 167eee0013eSWilly Tu } 168eee0013eSWilly Tu 169eee0013eSWilly Tu bool runningImage = false; 170eee0013eSWilly Tu // Look at Ids from 171eee0013eSWilly Tu // /xyz/openbmc_project/software/functional 172eee0013eSWilly Tu // to determine if this is a running image 1733544d2a7SEd Tanous if (std::ranges::find(functionalSwIds, swId) != 1743544d2a7SEd Tanous functionalSwIds.end()) 175eee0013eSWilly Tu { 176eee0013eSWilly Tu runningImage = true; 177eee0013eSWilly Tu } 178eee0013eSWilly Tu 179eee0013eSWilly Tu // Now grab its version info 180d1bde9e5SKrzysztof Grobelny sdbusplus::asio::getAllProperties( 181d1bde9e5SKrzysztof Grobelny *crow::connections::systemBus, obj.second[0].first, 182d1bde9e5SKrzysztof Grobelny obj.first, "xyz.openbmc_project.Software.Version", 183ac106bf6SEd Tanous [asyncResp, swId, runningImage, swVersionPurpose, 184eee0013eSWilly Tu activeVersionPropName, populateLinkToImages]( 1855e7e2dc5SEd Tanous const boost::system::error_code& ec3, 186eee0013eSWilly Tu const dbus::utility::DBusPropertiesMap& 187eee0013eSWilly Tu propertiesList) { 188eee0013eSWilly Tu if (ec3) 189eee0013eSWilly Tu { 19062598e31SEd Tanous BMCWEB_LOG_ERROR("error_code = {}", ec3); 19162598e31SEd Tanous BMCWEB_LOG_ERROR("error msg = {}", ec3.message()); 192eee0013eSWilly Tu // Have seen the code update app delete the D-Bus 193eee0013eSWilly Tu // object, during code update, between the call to 194eee0013eSWilly Tu // mapper and here. Just leave these properties off if 195eee0013eSWilly Tu // resource not found. 196eee0013eSWilly Tu if (ec3.value() == EBADR) 197eee0013eSWilly Tu { 198eee0013eSWilly Tu return; 199eee0013eSWilly Tu } 200ac106bf6SEd Tanous messages::internalError(asyncResp->res); 201eee0013eSWilly Tu return; 202eee0013eSWilly Tu } 203eee0013eSWilly Tu // example propertiesList 204eee0013eSWilly Tu // a{sv} 2 "Version" s 205eee0013eSWilly Tu // "IBM-witherspoon-OP9-v2.0.10-2.22" "Purpose" 206eee0013eSWilly Tu // s 207eee0013eSWilly Tu // "xyz.openbmc_project.Software.Version.VersionPurpose.Host" 208d1bde9e5SKrzysztof Grobelny const std::string* version = nullptr; 209d1bde9e5SKrzysztof Grobelny const std::string* swInvPurpose = nullptr; 210d1bde9e5SKrzysztof Grobelny 211d1bde9e5SKrzysztof Grobelny const bool success = sdbusplus::unpackPropertiesNoThrow( 212d1bde9e5SKrzysztof Grobelny dbus_utils::UnpackErrorPrinter(), propertiesList, 213d1bde9e5SKrzysztof Grobelny "Purpose", swInvPurpose, "Version", version); 214d1bde9e5SKrzysztof Grobelny 215d1bde9e5SKrzysztof Grobelny if (!success) 216eee0013eSWilly Tu { 217ac106bf6SEd Tanous messages::internalError(asyncResp->res); 218eee0013eSWilly Tu return; 219eee0013eSWilly Tu } 220eee0013eSWilly Tu 221d1bde9e5SKrzysztof Grobelny if (version == nullptr || version->empty()) 222eee0013eSWilly Tu { 223ac106bf6SEd Tanous messages::internalError(asyncResp->res); 224eee0013eSWilly Tu return; 225eee0013eSWilly Tu } 226d1bde9e5SKrzysztof Grobelny if (swInvPurpose == nullptr || 227d1bde9e5SKrzysztof Grobelny *swInvPurpose != swVersionPurpose) 228eee0013eSWilly Tu { 229eee0013eSWilly Tu // Not purpose we're looking for 230eee0013eSWilly Tu return; 231eee0013eSWilly Tu } 232eee0013eSWilly Tu 23362598e31SEd Tanous BMCWEB_LOG_DEBUG("Image ID: {}", swId); 23462598e31SEd Tanous BMCWEB_LOG_DEBUG("Running image: {}", runningImage); 23562598e31SEd Tanous BMCWEB_LOG_DEBUG("Image purpose: {}", *swInvPurpose); 236d1bde9e5SKrzysztof Grobelny 237eee0013eSWilly Tu if (populateLinkToImages) 238eee0013eSWilly Tu { 239eee0013eSWilly Tu nlohmann::json& softwareImageMembers = 240ac106bf6SEd Tanous asyncResp->res.jsonValue["Links"]["SoftwareImages"]; 241eee0013eSWilly Tu // Firmware images are at 242eee0013eSWilly Tu // /redfish/v1/UpdateService/FirmwareInventory/<Id> 243eee0013eSWilly Tu // e.g. .../FirmwareInventory/82d3ec86 244613dabeaSEd Tanous nlohmann::json::object_t member; 245ef4c65b7SEd Tanous member["@odata.id"] = boost::urls::format( 246ef4c65b7SEd Tanous "/redfish/v1/UpdateService/FirmwareInventory/{}", 247ef4c65b7SEd Tanous swId); 248b2ba3072SPatrick Williams softwareImageMembers.emplace_back(std::move(member)); 249ac106bf6SEd Tanous asyncResp->res 250eee0013eSWilly Tu .jsonValue["Links"]["SoftwareImages@odata.count"] = 251eee0013eSWilly Tu softwareImageMembers.size(); 252eee0013eSWilly Tu 253eee0013eSWilly Tu if (runningImage) 254eee0013eSWilly Tu { 255613dabeaSEd Tanous nlohmann::json::object_t runningMember; 256ef4c65b7SEd Tanous runningMember["@odata.id"] = boost::urls::format( 257ef4c65b7SEd Tanous "/redfish/v1/UpdateService/FirmwareInventory/{}", 258ef4c65b7SEd Tanous swId); 259eee0013eSWilly Tu // Create the link to the running image 260ac106bf6SEd Tanous asyncResp->res 261613dabeaSEd Tanous .jsonValue["Links"]["ActiveSoftwareImage"] = 262613dabeaSEd Tanous std::move(runningMember); 263eee0013eSWilly Tu } 264eee0013eSWilly Tu } 265eee0013eSWilly Tu if (!activeVersionPropName.empty() && runningImage) 266eee0013eSWilly Tu { 267ac106bf6SEd Tanous asyncResp->res.jsonValue[activeVersionPropName] = 268ac106bf6SEd Tanous *version; 269eee0013eSWilly Tu } 270d1bde9e5SKrzysztof Grobelny }); 271eee0013eSWilly Tu } 272e99073f5SGeorge Liu }); 273eee0013eSWilly Tu }); 274eee0013eSWilly Tu } 275eee0013eSWilly Tu 276eee0013eSWilly Tu /** 277eee0013eSWilly Tu * @brief Translate input swState to Redfish state 278eee0013eSWilly Tu * 279eee0013eSWilly Tu * This function will return the corresponding Redfish state 280eee0013eSWilly Tu * 281eee0013eSWilly Tu * @param[i] swState The OpenBMC software state 282eee0013eSWilly Tu * 283eee0013eSWilly Tu * @return The corresponding Redfish state 284eee0013eSWilly Tu */ 2850ec8b83dSEd Tanous inline resource::State getRedfishSwState(const std::string& swState) 286eee0013eSWilly Tu { 287eee0013eSWilly Tu if (swState == "xyz.openbmc_project.Software.Activation.Activations.Active") 288eee0013eSWilly Tu { 2890ec8b83dSEd Tanous return resource::State::Enabled; 290eee0013eSWilly Tu } 291eee0013eSWilly Tu if (swState == "xyz.openbmc_project.Software.Activation." 292eee0013eSWilly Tu "Activations.Activating") 293eee0013eSWilly Tu { 2940ec8b83dSEd Tanous return resource::State::Updating; 295eee0013eSWilly Tu } 296eee0013eSWilly Tu if (swState == "xyz.openbmc_project.Software.Activation." 297eee0013eSWilly Tu "Activations.StandbySpare") 298eee0013eSWilly Tu { 2990ec8b83dSEd Tanous return resource::State::StandbySpare; 300eee0013eSWilly Tu } 30162598e31SEd Tanous BMCWEB_LOG_DEBUG("Default sw state {} to Disabled", swState); 3020ec8b83dSEd Tanous return resource::State::Disabled; 303eee0013eSWilly Tu } 304eee0013eSWilly Tu 305eee0013eSWilly Tu /** 306eee0013eSWilly Tu * @brief Translate input swState to Redfish health state 307eee0013eSWilly Tu * 308eee0013eSWilly Tu * This function will return the corresponding Redfish health state 309eee0013eSWilly Tu * 310eee0013eSWilly Tu * @param[i] swState The OpenBMC software state 311eee0013eSWilly Tu * 312eee0013eSWilly Tu * @return The corresponding Redfish health state 313eee0013eSWilly Tu */ 314eee0013eSWilly Tu inline std::string getRedfishSwHealth(const std::string& swState) 315eee0013eSWilly Tu { 316eee0013eSWilly Tu if ((swState == 317eee0013eSWilly Tu "xyz.openbmc_project.Software.Activation.Activations.Active") || 318eee0013eSWilly Tu (swState == "xyz.openbmc_project.Software.Activation.Activations." 319eee0013eSWilly Tu "Activating") || 320eee0013eSWilly Tu (swState == 321eee0013eSWilly Tu "xyz.openbmc_project.Software.Activation.Activations.Ready")) 322eee0013eSWilly Tu { 323eee0013eSWilly Tu return "OK"; 324eee0013eSWilly Tu } 32562598e31SEd Tanous BMCWEB_LOG_DEBUG("Sw state {} to Warning", swState); 326eee0013eSWilly Tu return "Warning"; 327eee0013eSWilly Tu } 328eee0013eSWilly Tu 329eee0013eSWilly Tu /** 330eee0013eSWilly Tu * @brief Put status of input swId into json response 331eee0013eSWilly Tu * 332eee0013eSWilly Tu * This function will put the appropriate Redfish state of the input 333eee0013eSWilly Tu * software id to ["Status"]["State"] within the json response 334eee0013eSWilly Tu * 335ac106bf6SEd Tanous * @param[i,o] asyncResp Async response object 336eee0013eSWilly Tu * @param[i] swId The software ID to get status for 337eee0013eSWilly Tu * @param[i] dbusSvc The dbus service implementing the software object 338eee0013eSWilly Tu * 339eee0013eSWilly Tu * @return void 340eee0013eSWilly Tu */ 341eee0013eSWilly Tu inline void getSwStatus(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 342eee0013eSWilly Tu const std::shared_ptr<std::string>& swId, 343eee0013eSWilly Tu const std::string& dbusSvc) 344eee0013eSWilly Tu { 34562598e31SEd Tanous BMCWEB_LOG_DEBUG("getSwStatus: swId {} svc {}", *swId, dbusSvc); 346eee0013eSWilly Tu 347d1bde9e5SKrzysztof Grobelny sdbusplus::asio::getAllProperties( 348d1bde9e5SKrzysztof Grobelny *crow::connections::systemBus, dbusSvc, 349d1bde9e5SKrzysztof Grobelny "/xyz/openbmc_project/software/" + *swId, 350d1bde9e5SKrzysztof Grobelny "xyz.openbmc_project.Software.Activation", 351eee0013eSWilly Tu [asyncResp, 3528b24275dSEd Tanous swId](const boost::system::error_code& ec, 353eee0013eSWilly Tu const dbus::utility::DBusPropertiesMap& propertiesList) { 3548b24275dSEd Tanous if (ec) 355eee0013eSWilly Tu { 356eee0013eSWilly Tu // not all swtypes are updateable, this is ok 357*539d8c6bSEd Tanous asyncResp->res.jsonValue["Status"]["State"] = 358*539d8c6bSEd Tanous resource::State::Enabled; 359eee0013eSWilly Tu return; 360eee0013eSWilly Tu } 361d1bde9e5SKrzysztof Grobelny 362eee0013eSWilly Tu const std::string* swInvActivation = nullptr; 363d1bde9e5SKrzysztof Grobelny 364d1bde9e5SKrzysztof Grobelny const bool success = sdbusplus::unpackPropertiesNoThrow( 365d1bde9e5SKrzysztof Grobelny dbus_utils::UnpackErrorPrinter(), propertiesList, "Activation", 366d1bde9e5SKrzysztof Grobelny swInvActivation); 367d1bde9e5SKrzysztof Grobelny 368d1bde9e5SKrzysztof Grobelny if (!success) 369eee0013eSWilly Tu { 370d1bde9e5SKrzysztof Grobelny messages::internalError(asyncResp->res); 371d1bde9e5SKrzysztof Grobelny return; 372eee0013eSWilly Tu } 373eee0013eSWilly Tu 374eee0013eSWilly Tu if (swInvActivation == nullptr) 375eee0013eSWilly Tu { 376eee0013eSWilly Tu messages::internalError(asyncResp->res); 377eee0013eSWilly Tu return; 378eee0013eSWilly Tu } 379d1bde9e5SKrzysztof Grobelny 38062598e31SEd Tanous BMCWEB_LOG_DEBUG("getSwStatus: Activation {}", *swInvActivation); 381eee0013eSWilly Tu asyncResp->res.jsonValue["Status"]["State"] = 382eee0013eSWilly Tu getRedfishSwState(*swInvActivation); 383eee0013eSWilly Tu asyncResp->res.jsonValue["Status"]["Health"] = 384eee0013eSWilly Tu getRedfishSwHealth(*swInvActivation); 385d1bde9e5SKrzysztof Grobelny }); 386eee0013eSWilly Tu } 387eee0013eSWilly Tu 388c018f705SJagpal Singh Gill inline void handleUpdateableEndpoints( 389c018f705SJagpal Singh Gill const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 390c018f705SJagpal Singh Gill const std::shared_ptr<std::string>& swId, 391c018f705SJagpal Singh Gill const boost::system::error_code& ec, 392c018f705SJagpal Singh Gill const dbus::utility::MapperEndPoints& objPaths) 393c018f705SJagpal Singh Gill { 394c018f705SJagpal Singh Gill if (ec) 395c018f705SJagpal Singh Gill { 396c018f705SJagpal Singh Gill BMCWEB_LOG_DEBUG(" error_code = {} error msg = {}", ec, ec.message()); 397c018f705SJagpal Singh Gill // System can exist with no updateable software, 398c018f705SJagpal Singh Gill // so don't throw error here. 399c018f705SJagpal Singh Gill return; 400c018f705SJagpal Singh Gill } 401c018f705SJagpal Singh Gill sdbusplus::message::object_path reqSwObjPath( 402c018f705SJagpal Singh Gill "/xyz/openbmc_project/software"); 403c018f705SJagpal Singh Gill reqSwObjPath = reqSwObjPath / *swId; 404c018f705SJagpal Singh Gill 405c018f705SJagpal Singh Gill if (std::ranges::find(objPaths, reqSwObjPath.str) != objPaths.end()) 406c018f705SJagpal Singh Gill { 407c018f705SJagpal Singh Gill asyncResp->res.jsonValue["Updateable"] = true; 408c018f705SJagpal Singh Gill return; 409c018f705SJagpal Singh Gill } 410c018f705SJagpal Singh Gill } 411c018f705SJagpal Singh Gill 412c018f705SJagpal Singh Gill inline void 413c018f705SJagpal Singh Gill handleUpdateableObject(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 414c018f705SJagpal Singh Gill const boost::system::error_code& ec, 415c018f705SJagpal Singh Gill const dbus::utility::MapperGetObject& objectInfo) 416c018f705SJagpal Singh Gill { 417c018f705SJagpal Singh Gill if (ec) 418c018f705SJagpal Singh Gill { 419c018f705SJagpal Singh Gill BMCWEB_LOG_DEBUG(" error_code = {} error msg = {}", ec, ec.message()); 420c018f705SJagpal Singh Gill // System can exist with no updateable software, 421c018f705SJagpal Singh Gill // so don't throw error here. 422c018f705SJagpal Singh Gill return; 423c018f705SJagpal Singh Gill } 424c018f705SJagpal Singh Gill if (objectInfo.empty()) 425c018f705SJagpal Singh Gill { 426c018f705SJagpal Singh Gill BMCWEB_LOG_DEBUG("No updateable software found"); 427c018f705SJagpal Singh Gill // System can exist with no updateable software, 428c018f705SJagpal Singh Gill // so don't throw error here. 429c018f705SJagpal Singh Gill return; 430c018f705SJagpal Singh Gill } 431c018f705SJagpal Singh Gill asyncResp->res.jsonValue["Updateable"] = true; 432c018f705SJagpal Singh Gill } 433c018f705SJagpal Singh Gill 434eee0013eSWilly Tu /** 435eee0013eSWilly Tu * @brief Updates programmable status of input swId into json response 436eee0013eSWilly Tu * 437eee0013eSWilly Tu * This function checks whether software inventory component 438eee0013eSWilly Tu * can be programmable or not and fill's the "Updatable" 439eee0013eSWilly Tu * Property. 440eee0013eSWilly Tu * 441eee0013eSWilly Tu * @param[i,o] asyncResp Async response object 442eee0013eSWilly Tu * @param[i] swId The software ID 443eee0013eSWilly Tu */ 444eee0013eSWilly Tu inline void 445eee0013eSWilly Tu getSwUpdatableStatus(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 446eee0013eSWilly Tu const std::shared_ptr<std::string>& swId) 447eee0013eSWilly Tu { 448c018f705SJagpal Singh Gill if constexpr (BMCWEB_REDFISH_UPDATESERVICE_USE_DBUS) 449c018f705SJagpal Singh Gill { 450c018f705SJagpal Singh Gill sdbusplus::message::object_path swObjectPath( 451c018f705SJagpal Singh Gill "/xyz/openbmc_project/software"); 452c018f705SJagpal Singh Gill swObjectPath = swObjectPath / *swId; 453c018f705SJagpal Singh Gill constexpr std::array<std::string_view, 1> interfaces = { 454c018f705SJagpal Singh Gill "xyz.openbmc_project.Software.Update"}; 455c018f705SJagpal Singh Gill dbus::utility::getDbusObject( 456c018f705SJagpal Singh Gill swObjectPath.str, interfaces, 457c018f705SJagpal Singh Gill std::bind_front(handleUpdateableObject, asyncResp)); 458c018f705SJagpal Singh Gill } 459c018f705SJagpal Singh Gill else 460c018f705SJagpal Singh Gill { 4616c3e9451SGeorge Liu dbus::utility::getAssociationEndPoints( 462eee0013eSWilly Tu "/xyz/openbmc_project/software/updateable", 463c018f705SJagpal Singh Gill std::bind_front(handleUpdateableEndpoints, asyncResp, swId)); 464eee0013eSWilly Tu } 465eee0013eSWilly Tu } 466eee0013eSWilly Tu 467eee0013eSWilly Tu } // namespace sw_util 468eee0013eSWilly Tu } // namespace redfish 469