xref: /openbmc/bmcweb/features/redfish/include/utils/sw_utils.hpp (revision 6c3e94511027133db407f9e1c3c628927ec1332f)
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>
10eee0013eSWilly Tu #include <sdbusplus/asio/property.hpp>
11d1bde9e5SKrzysztof Grobelny #include <sdbusplus/unpack_properties.hpp>
12eee0013eSWilly Tu 
13eee0013eSWilly Tu #include <algorithm>
14e99073f5SGeorge Liu #include <array>
15eee0013eSWilly Tu #include <string>
16e99073f5SGeorge Liu #include <string_view>
17eee0013eSWilly Tu #include <vector>
18eee0013eSWilly Tu 
19eee0013eSWilly Tu namespace redfish
20eee0013eSWilly Tu {
21eee0013eSWilly Tu namespace sw_util
22eee0013eSWilly Tu {
23eee0013eSWilly Tu /* @brief String that indicates a bios software instance */
24eee0013eSWilly Tu constexpr const char* biosPurpose =
25eee0013eSWilly Tu     "xyz.openbmc_project.Software.Version.VersionPurpose.Host";
26eee0013eSWilly Tu 
27eee0013eSWilly Tu /* @brief String that indicates a BMC software instance */
28eee0013eSWilly Tu constexpr const char* bmcPurpose =
29eee0013eSWilly Tu     "xyz.openbmc_project.Software.Version.VersionPurpose.BMC";
30eee0013eSWilly Tu 
31eee0013eSWilly Tu /**
32eee0013eSWilly Tu  * @brief Populate the running software version and image links
33eee0013eSWilly Tu  *
34eee0013eSWilly Tu  * @param[i,o] aResp             Async response object
35eee0013eSWilly Tu  * @param[i]   swVersionPurpose  Indicates what target to look for
36eee0013eSWilly Tu  * @param[i]   activeVersionPropName  Index in aResp->res.jsonValue to write
37eee0013eSWilly Tu  * the running software version to
38eee0013eSWilly Tu  * @param[i]   populateLinkToImages  Populate aResp->res "Links"
39eee0013eSWilly Tu  * "ActiveSoftwareImage" with a link to the running software image and
40eee0013eSWilly Tu  * "SoftwareImages" with a link to the all its software images
41eee0013eSWilly Tu  *
42eee0013eSWilly Tu  * @return void
43eee0013eSWilly Tu  */
44eee0013eSWilly Tu inline void
45eee0013eSWilly Tu     populateSoftwareInformation(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
46eee0013eSWilly Tu                                 const std::string& swVersionPurpose,
47eee0013eSWilly Tu                                 const std::string& activeVersionPropName,
48eee0013eSWilly Tu                                 const bool populateLinkToImages)
49eee0013eSWilly Tu {
50eee0013eSWilly Tu     // Used later to determine running (known on Redfish as active) Sw images
51a4eb761aSGeorge Liu     dbus::utility::getAssociationEndPoints(
52eee0013eSWilly Tu         "/xyz/openbmc_project/software/functional",
53a4eb761aSGeorge Liu         [aResp, swVersionPurpose, activeVersionPropName, populateLinkToImages](
54a4eb761aSGeorge Liu             const boost::system::error_code& ec,
55a4eb761aSGeorge Liu             const dbus::utility::MapperEndPoints& functionalSw) {
56eee0013eSWilly Tu         BMCWEB_LOG_DEBUG << "populateSoftwareInformation enter";
57eee0013eSWilly Tu         if (ec)
58eee0013eSWilly Tu         {
59eee0013eSWilly Tu             BMCWEB_LOG_ERROR << "error_code = " << ec;
60eee0013eSWilly Tu             BMCWEB_LOG_ERROR << "error msg = " << ec.message();
61eee0013eSWilly Tu             messages::internalError(aResp->res);
62eee0013eSWilly Tu             return;
63eee0013eSWilly Tu         }
64eee0013eSWilly Tu 
65eee0013eSWilly Tu         if (functionalSw.empty())
66eee0013eSWilly Tu         {
67eee0013eSWilly Tu             // Could keep going and try to populate SoftwareImages but
68eee0013eSWilly Tu             // something is seriously wrong, so just fail
69eee0013eSWilly Tu             BMCWEB_LOG_ERROR << "Zero functional software in system";
70eee0013eSWilly Tu             messages::internalError(aResp->res);
71eee0013eSWilly Tu             return;
72eee0013eSWilly Tu         }
73eee0013eSWilly Tu 
74eee0013eSWilly Tu         std::vector<std::string> functionalSwIds;
75eee0013eSWilly Tu         // example functionalSw:
76eee0013eSWilly Tu         // v as 2 "/xyz/openbmc_project/software/ace821ef"
77eee0013eSWilly Tu         //        "/xyz/openbmc_project/software/230fb078"
78c6830d5fSGunnar Mills         for (const auto& sw : functionalSw)
79eee0013eSWilly Tu         {
80c6830d5fSGunnar Mills             sdbusplus::message::object_path path(sw);
81eee0013eSWilly Tu             std::string leaf = path.filename();
82eee0013eSWilly Tu             if (leaf.empty())
83eee0013eSWilly Tu             {
84eee0013eSWilly Tu                 continue;
85eee0013eSWilly Tu             }
86eee0013eSWilly Tu 
87eee0013eSWilly Tu             functionalSwIds.push_back(leaf);
88eee0013eSWilly Tu         }
89eee0013eSWilly Tu 
90e99073f5SGeorge Liu         constexpr std::array<std::string_view, 1> interfaces = {
91e99073f5SGeorge Liu             "xyz.openbmc_project.Software.Version"};
92e99073f5SGeorge Liu         dbus::utility::getSubTree(
93e99073f5SGeorge Liu             "/xyz/openbmc_project/software", 0, interfaces,
94eee0013eSWilly Tu             [aResp, swVersionPurpose, activeVersionPropName,
95eee0013eSWilly Tu              populateLinkToImages, functionalSwIds](
96e99073f5SGeorge Liu                 const boost::system::error_code& ec2,
97eee0013eSWilly Tu                 const dbus::utility::MapperGetSubTreeResponse& subtree) {
98eee0013eSWilly Tu             if (ec2)
99eee0013eSWilly Tu             {
100eee0013eSWilly Tu                 BMCWEB_LOG_ERROR << "error_code = " << ec2;
101eee0013eSWilly Tu                 BMCWEB_LOG_ERROR << "error msg = " << ec2.message();
102eee0013eSWilly Tu                 messages::internalError(aResp->res);
103eee0013eSWilly Tu                 return;
104eee0013eSWilly Tu             }
105eee0013eSWilly Tu 
106eee0013eSWilly Tu             BMCWEB_LOG_DEBUG << "Found " << subtree.size() << " images";
107eee0013eSWilly Tu 
108eee0013eSWilly Tu             for (const std::pair<std::string,
109eee0013eSWilly Tu                                  std::vector<std::pair<
110eee0013eSWilly Tu                                      std::string, std::vector<std::string>>>>&
111eee0013eSWilly Tu                      obj : subtree)
112eee0013eSWilly Tu             {
113eee0013eSWilly Tu 
114eee0013eSWilly Tu                 sdbusplus::message::object_path path(obj.first);
115eee0013eSWilly Tu                 std::string swId = path.filename();
116eee0013eSWilly Tu                 if (swId.empty())
117eee0013eSWilly Tu                 {
118eee0013eSWilly Tu                     messages::internalError(aResp->res);
119eee0013eSWilly Tu                     BMCWEB_LOG_ERROR << "Invalid software ID";
120eee0013eSWilly Tu 
121eee0013eSWilly Tu                     return;
122eee0013eSWilly Tu                 }
123eee0013eSWilly Tu 
124eee0013eSWilly Tu                 bool runningImage = false;
125eee0013eSWilly Tu                 // Look at Ids from
126eee0013eSWilly Tu                 // /xyz/openbmc_project/software/functional
127eee0013eSWilly Tu                 // to determine if this is a running image
128eee0013eSWilly Tu                 if (std::find(functionalSwIds.begin(), functionalSwIds.end(),
129eee0013eSWilly Tu                               swId) != functionalSwIds.end())
130eee0013eSWilly Tu                 {
131eee0013eSWilly Tu                     runningImage = true;
132eee0013eSWilly Tu                 }
133eee0013eSWilly Tu 
134eee0013eSWilly Tu                 // Now grab its version info
135d1bde9e5SKrzysztof Grobelny                 sdbusplus::asio::getAllProperties(
136d1bde9e5SKrzysztof Grobelny                     *crow::connections::systemBus, obj.second[0].first,
137d1bde9e5SKrzysztof Grobelny                     obj.first, "xyz.openbmc_project.Software.Version",
138eee0013eSWilly Tu                     [aResp, swId, runningImage, swVersionPurpose,
139eee0013eSWilly Tu                      activeVersionPropName, populateLinkToImages](
1405e7e2dc5SEd Tanous                         const boost::system::error_code& ec3,
141eee0013eSWilly Tu                         const dbus::utility::DBusPropertiesMap&
142eee0013eSWilly Tu                             propertiesList) {
143eee0013eSWilly Tu                     if (ec3)
144eee0013eSWilly Tu                     {
145eee0013eSWilly Tu                         BMCWEB_LOG_ERROR << "error_code = " << ec3;
146eee0013eSWilly Tu                         BMCWEB_LOG_ERROR << "error msg = " << ec3.message();
147eee0013eSWilly Tu                         // Have seen the code update app delete the D-Bus
148eee0013eSWilly Tu                         // object, during code update, between the call to
149eee0013eSWilly Tu                         // mapper and here. Just leave these properties off if
150eee0013eSWilly Tu                         // resource not found.
151eee0013eSWilly Tu                         if (ec3.value() == EBADR)
152eee0013eSWilly Tu                         {
153eee0013eSWilly Tu                             return;
154eee0013eSWilly Tu                         }
155eee0013eSWilly Tu                         messages::internalError(aResp->res);
156eee0013eSWilly Tu                         return;
157eee0013eSWilly Tu                     }
158eee0013eSWilly Tu                     // example propertiesList
159eee0013eSWilly Tu                     // a{sv} 2 "Version" s
160eee0013eSWilly Tu                     // "IBM-witherspoon-OP9-v2.0.10-2.22" "Purpose"
161eee0013eSWilly Tu                     // s
162eee0013eSWilly Tu                     // "xyz.openbmc_project.Software.Version.VersionPurpose.Host"
163d1bde9e5SKrzysztof Grobelny                     const std::string* version = nullptr;
164d1bde9e5SKrzysztof Grobelny                     const std::string* swInvPurpose = nullptr;
165d1bde9e5SKrzysztof Grobelny 
166d1bde9e5SKrzysztof Grobelny                     const bool success = sdbusplus::unpackPropertiesNoThrow(
167d1bde9e5SKrzysztof Grobelny                         dbus_utils::UnpackErrorPrinter(), propertiesList,
168d1bde9e5SKrzysztof Grobelny                         "Purpose", swInvPurpose, "Version", version);
169d1bde9e5SKrzysztof Grobelny 
170d1bde9e5SKrzysztof Grobelny                     if (!success)
171eee0013eSWilly Tu                     {
172eee0013eSWilly Tu                         messages::internalError(aResp->res);
173eee0013eSWilly Tu                         return;
174eee0013eSWilly Tu                     }
175eee0013eSWilly Tu 
176d1bde9e5SKrzysztof Grobelny                     if (version == nullptr || version->empty())
177eee0013eSWilly Tu                     {
178eee0013eSWilly Tu                         messages::internalError(aResp->res);
179eee0013eSWilly Tu                         return;
180eee0013eSWilly Tu                     }
181d1bde9e5SKrzysztof Grobelny                     if (swInvPurpose == nullptr ||
182d1bde9e5SKrzysztof Grobelny                         *swInvPurpose != swVersionPurpose)
183eee0013eSWilly Tu                     {
184eee0013eSWilly Tu                         // Not purpose we're looking for
185eee0013eSWilly Tu                         return;
186eee0013eSWilly Tu                     }
187eee0013eSWilly Tu 
188d1bde9e5SKrzysztof Grobelny                     BMCWEB_LOG_DEBUG << "Image ID: " << swId;
189d1bde9e5SKrzysztof Grobelny                     BMCWEB_LOG_DEBUG << "Running image: " << runningImage;
190d1bde9e5SKrzysztof Grobelny                     BMCWEB_LOG_DEBUG << "Image purpose: " << *swInvPurpose;
191d1bde9e5SKrzysztof Grobelny 
192eee0013eSWilly Tu                     if (populateLinkToImages)
193eee0013eSWilly Tu                     {
194eee0013eSWilly Tu                         nlohmann::json& softwareImageMembers =
195eee0013eSWilly Tu                             aResp->res.jsonValue["Links"]["SoftwareImages"];
196eee0013eSWilly Tu                         // Firmware images are at
197eee0013eSWilly Tu                         // /redfish/v1/UpdateService/FirmwareInventory/<Id>
198eee0013eSWilly Tu                         // e.g. .../FirmwareInventory/82d3ec86
199613dabeaSEd Tanous                         nlohmann::json::object_t member;
200eddfc437SWilly Tu                         member["@odata.id"] = crow::utility::urlFromPieces(
201eddfc437SWilly Tu                             "redfish", "v1", "UpdateService",
202eddfc437SWilly Tu                             "FirmwareInventory", swId);
203613dabeaSEd Tanous                         softwareImageMembers.push_back(std::move(member));
204eee0013eSWilly Tu                         aResp->res
205eee0013eSWilly Tu                             .jsonValue["Links"]["SoftwareImages@odata.count"] =
206eee0013eSWilly Tu                             softwareImageMembers.size();
207eee0013eSWilly Tu 
208eee0013eSWilly Tu                         if (runningImage)
209eee0013eSWilly Tu                         {
210613dabeaSEd Tanous                             nlohmann::json::object_t runningMember;
211613dabeaSEd Tanous                             runningMember["@odata.id"] =
212eddfc437SWilly Tu                                 crow::utility::urlFromPieces(
213eddfc437SWilly Tu                                     "redfish", "v1", "UpdateService",
214eddfc437SWilly Tu                                     "FirmwareInventory", swId);
215eee0013eSWilly Tu                             // Create the link to the running image
216eee0013eSWilly Tu                             aResp->res
217613dabeaSEd Tanous                                 .jsonValue["Links"]["ActiveSoftwareImage"] =
218613dabeaSEd Tanous                                 std::move(runningMember);
219eee0013eSWilly Tu                         }
220eee0013eSWilly Tu                     }
221eee0013eSWilly Tu                     if (!activeVersionPropName.empty() && runningImage)
222eee0013eSWilly Tu                     {
223d1bde9e5SKrzysztof Grobelny                         aResp->res.jsonValue[activeVersionPropName] = *version;
224eee0013eSWilly Tu                     }
225d1bde9e5SKrzysztof Grobelny                     });
226eee0013eSWilly Tu             }
227e99073f5SGeorge Liu             });
228eee0013eSWilly Tu         });
229eee0013eSWilly Tu }
230eee0013eSWilly Tu 
231eee0013eSWilly Tu /**
232eee0013eSWilly Tu  * @brief Translate input swState to Redfish state
233eee0013eSWilly Tu  *
234eee0013eSWilly Tu  * This function will return the corresponding Redfish state
235eee0013eSWilly Tu  *
236eee0013eSWilly Tu  * @param[i]   swState  The OpenBMC software state
237eee0013eSWilly Tu  *
238eee0013eSWilly Tu  * @return The corresponding Redfish state
239eee0013eSWilly Tu  */
2400ec8b83dSEd Tanous inline resource::State getRedfishSwState(const std::string& swState)
241eee0013eSWilly Tu {
242eee0013eSWilly Tu     if (swState == "xyz.openbmc_project.Software.Activation.Activations.Active")
243eee0013eSWilly Tu     {
2440ec8b83dSEd Tanous         return resource::State::Enabled;
245eee0013eSWilly Tu     }
246eee0013eSWilly Tu     if (swState == "xyz.openbmc_project.Software.Activation."
247eee0013eSWilly Tu                    "Activations.Activating")
248eee0013eSWilly Tu     {
2490ec8b83dSEd Tanous         return resource::State::Updating;
250eee0013eSWilly Tu     }
251eee0013eSWilly Tu     if (swState == "xyz.openbmc_project.Software.Activation."
252eee0013eSWilly Tu                    "Activations.StandbySpare")
253eee0013eSWilly Tu     {
2540ec8b83dSEd Tanous         return resource::State::StandbySpare;
255eee0013eSWilly Tu     }
256eee0013eSWilly Tu     BMCWEB_LOG_DEBUG << "Default sw state " << swState << " to Disabled";
2570ec8b83dSEd Tanous     return resource::State::Disabled;
258eee0013eSWilly Tu }
259eee0013eSWilly Tu 
260eee0013eSWilly Tu /**
261eee0013eSWilly Tu  * @brief Translate input swState to Redfish health state
262eee0013eSWilly Tu  *
263eee0013eSWilly Tu  * This function will return the corresponding Redfish health state
264eee0013eSWilly Tu  *
265eee0013eSWilly Tu  * @param[i]   swState  The OpenBMC software state
266eee0013eSWilly Tu  *
267eee0013eSWilly Tu  * @return The corresponding Redfish health state
268eee0013eSWilly Tu  */
269eee0013eSWilly Tu inline std::string getRedfishSwHealth(const std::string& swState)
270eee0013eSWilly Tu {
271eee0013eSWilly Tu     if ((swState ==
272eee0013eSWilly Tu          "xyz.openbmc_project.Software.Activation.Activations.Active") ||
273eee0013eSWilly Tu         (swState == "xyz.openbmc_project.Software.Activation.Activations."
274eee0013eSWilly Tu                     "Activating") ||
275eee0013eSWilly Tu         (swState ==
276eee0013eSWilly Tu          "xyz.openbmc_project.Software.Activation.Activations.Ready"))
277eee0013eSWilly Tu     {
278eee0013eSWilly Tu         return "OK";
279eee0013eSWilly Tu     }
280eee0013eSWilly Tu     BMCWEB_LOG_DEBUG << "Sw state " << swState << " to Warning";
281eee0013eSWilly Tu     return "Warning";
282eee0013eSWilly Tu }
283eee0013eSWilly Tu 
284eee0013eSWilly Tu /**
285eee0013eSWilly Tu  * @brief Put status of input swId into json response
286eee0013eSWilly Tu  *
287eee0013eSWilly Tu  * This function will put the appropriate Redfish state of the input
288eee0013eSWilly Tu  * software id to ["Status"]["State"] within the json response
289eee0013eSWilly Tu  *
290eee0013eSWilly Tu  * @param[i,o] aResp    Async response object
291eee0013eSWilly Tu  * @param[i]   swId     The software ID to get status for
292eee0013eSWilly Tu  * @param[i]   dbusSvc  The dbus service implementing the software object
293eee0013eSWilly Tu  *
294eee0013eSWilly Tu  * @return void
295eee0013eSWilly Tu  */
296eee0013eSWilly Tu inline void getSwStatus(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
297eee0013eSWilly Tu                         const std::shared_ptr<std::string>& swId,
298eee0013eSWilly Tu                         const std::string& dbusSvc)
299eee0013eSWilly Tu {
300eee0013eSWilly Tu     BMCWEB_LOG_DEBUG << "getSwStatus: swId " << *swId << " svc " << dbusSvc;
301eee0013eSWilly Tu 
302d1bde9e5SKrzysztof Grobelny     sdbusplus::asio::getAllProperties(
303d1bde9e5SKrzysztof Grobelny         *crow::connections::systemBus, dbusSvc,
304d1bde9e5SKrzysztof Grobelny         "/xyz/openbmc_project/software/" + *swId,
305d1bde9e5SKrzysztof Grobelny         "xyz.openbmc_project.Software.Activation",
306eee0013eSWilly Tu         [asyncResp,
3075e7e2dc5SEd Tanous          swId](const boost::system::error_code& errorCode,
308eee0013eSWilly Tu                const dbus::utility::DBusPropertiesMap& propertiesList) {
309eee0013eSWilly Tu         if (errorCode)
310eee0013eSWilly Tu         {
311eee0013eSWilly Tu             // not all swtypes are updateable, this is ok
312eee0013eSWilly Tu             asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
313eee0013eSWilly Tu             return;
314eee0013eSWilly Tu         }
315d1bde9e5SKrzysztof Grobelny 
316eee0013eSWilly Tu         const std::string* swInvActivation = nullptr;
317d1bde9e5SKrzysztof Grobelny 
318d1bde9e5SKrzysztof Grobelny         const bool success = sdbusplus::unpackPropertiesNoThrow(
319d1bde9e5SKrzysztof Grobelny             dbus_utils::UnpackErrorPrinter(), propertiesList, "Activation",
320d1bde9e5SKrzysztof Grobelny             swInvActivation);
321d1bde9e5SKrzysztof Grobelny 
322d1bde9e5SKrzysztof Grobelny         if (!success)
323eee0013eSWilly Tu         {
324d1bde9e5SKrzysztof Grobelny             messages::internalError(asyncResp->res);
325d1bde9e5SKrzysztof Grobelny             return;
326eee0013eSWilly Tu         }
327eee0013eSWilly Tu 
328eee0013eSWilly Tu         if (swInvActivation == nullptr)
329eee0013eSWilly Tu         {
330eee0013eSWilly Tu             messages::internalError(asyncResp->res);
331eee0013eSWilly Tu             return;
332eee0013eSWilly Tu         }
333d1bde9e5SKrzysztof Grobelny 
334eee0013eSWilly Tu         BMCWEB_LOG_DEBUG << "getSwStatus: Activation " << *swInvActivation;
335eee0013eSWilly Tu         asyncResp->res.jsonValue["Status"]["State"] =
336eee0013eSWilly Tu             getRedfishSwState(*swInvActivation);
337eee0013eSWilly Tu         asyncResp->res.jsonValue["Status"]["Health"] =
338eee0013eSWilly Tu             getRedfishSwHealth(*swInvActivation);
339d1bde9e5SKrzysztof Grobelny         });
340eee0013eSWilly Tu }
341eee0013eSWilly Tu 
342eee0013eSWilly Tu /**
343eee0013eSWilly Tu  * @brief Updates programmable status of input swId into json response
344eee0013eSWilly Tu  *
345eee0013eSWilly Tu  * This function checks whether software inventory component
346eee0013eSWilly Tu  * can be programmable or not and fill's the "Updatable"
347eee0013eSWilly Tu  * Property.
348eee0013eSWilly Tu  *
349eee0013eSWilly Tu  * @param[i,o] asyncResp  Async response object
350eee0013eSWilly Tu  * @param[i]   swId       The software ID
351eee0013eSWilly Tu  */
352eee0013eSWilly Tu inline void
353eee0013eSWilly Tu     getSwUpdatableStatus(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
354eee0013eSWilly Tu                          const std::shared_ptr<std::string>& swId)
355eee0013eSWilly Tu {
356*6c3e9451SGeorge Liu     dbus::utility::getAssociationEndPoints(
357eee0013eSWilly Tu         "/xyz/openbmc_project/software/updateable",
3585e7e2dc5SEd Tanous         [asyncResp, swId](const boost::system::error_code& ec,
359*6c3e9451SGeorge Liu                           const dbus::utility::MapperEndPoints& objPaths) {
360eee0013eSWilly Tu         if (ec)
361eee0013eSWilly Tu         {
362eee0013eSWilly Tu             BMCWEB_LOG_DEBUG << " error_code = " << ec
363eee0013eSWilly Tu                              << " error msg =  " << ec.message();
364eee0013eSWilly Tu             // System can exist with no updateable software,
365eee0013eSWilly Tu             // so don't throw error here.
366eee0013eSWilly Tu             return;
367eee0013eSWilly Tu         }
368eee0013eSWilly Tu         std::string reqSwObjPath = "/xyz/openbmc_project/software/" + *swId;
369eee0013eSWilly Tu 
370eee0013eSWilly Tu         if (std::find(objPaths.begin(), objPaths.end(), reqSwObjPath) !=
371eee0013eSWilly Tu             objPaths.end())
372eee0013eSWilly Tu         {
37383edb08fSGunnar Mills             asyncResp->res.jsonValue["Updateable"] = true;
374eee0013eSWilly Tu             return;
375eee0013eSWilly Tu         }
376eee0013eSWilly Tu         });
377eee0013eSWilly Tu }
378eee0013eSWilly Tu 
379eee0013eSWilly Tu } // namespace sw_util
380eee0013eSWilly Tu } // namespace redfish
381