xref: /openbmc/bmcweb/features/redfish/include/utils/sw_utils.hpp (revision 539d8c6bc399e516d39bcaa18262cf206f4c1035)
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