update service: updateable firmware logic change

Update the way a firmware inventory item is considered updateable or not
based on the update D-Bus interface change. For more details refer to
design -
https://gerrit.openbmc.org/c/openbmc/phosphor-dbus-interfaces/+/65738
https://gerrit.openbmc.org/c/openbmc/docs/+/65739

Tested:
```
> curl -k -H "X-Auth-Token: $token" -X GET https://${bmc}/redfish/v1/UpdateService/FirmwareInventory/3c956be0
{
  "@odata.id": "/redfish/v1/UpdateService/FirmwareInventory/3c956be0",
  "@odata.type": "#SoftwareInventory.v1_1_0.SoftwareInventory",
  "Description": "BMC image",
  "Id": "3c956be0",
  "Name": "Software Inventory",
  "RelatedItem": [
    {
      "@odata.id": "/redfish/v1/Managers/bmc"
    }
  ],
  "RelatedItem@odata.count": 1,
  "Status": {
    "Health": "OK",
    "HealthRollup": "OK",
    "State": "Enabled"
  },
  "Updateable": true,
  "Version": "2.16.0-dev-1063-g57294f9ba2-dirty"
}
```

Redfish service validator passing:
```
Elapsed time: 0:04:33
metadataNamespaces: 3727
pass: 5184
passAction: 16
passGet: 213
passRedfishUri: 205
skipNoSchema: 3
skipOptional: 3535
unvalidated: 1
warnDeprecated: 5
warningPresent: 6
```

Change-Id: If0e652c72866356ba09985b4ad2cfe76bf6a1142
Signed-off-by: Jagpal Singh Gill <paligill@gmail.com>
diff --git a/redfish-core/include/utils/sw_utils.hpp b/redfish-core/include/utils/sw_utils.hpp
index 8a715e6..f5c4f0f 100644
--- a/redfish-core/include/utils/sw_utils.hpp
+++ b/redfish-core/include/utils/sw_utils.hpp
@@ -340,6 +340,52 @@
     });
 }
 
+inline void handleUpdateableEndpoints(
+    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+    const std::shared_ptr<std::string>& swId,
+    const boost::system::error_code& ec,
+    const dbus::utility::MapperEndPoints& objPaths)
+{
+    if (ec)
+    {
+        BMCWEB_LOG_DEBUG(" error_code = {} error msg =  {}", ec, ec.message());
+        // System can exist with no updateable software,
+        // so don't throw error here.
+        return;
+    }
+    sdbusplus::message::object_path reqSwObjPath(
+        "/xyz/openbmc_project/software");
+    reqSwObjPath = reqSwObjPath / *swId;
+
+    if (std::ranges::find(objPaths, reqSwObjPath.str) != objPaths.end())
+    {
+        asyncResp->res.jsonValue["Updateable"] = true;
+        return;
+    }
+}
+
+inline void
+    handleUpdateableObject(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+                           const boost::system::error_code& ec,
+                           const dbus::utility::MapperGetObject& objectInfo)
+{
+    if (ec)
+    {
+        BMCWEB_LOG_DEBUG(" error_code = {} error msg =  {}", ec, ec.message());
+        // System can exist with no updateable software,
+        // so don't throw error here.
+        return;
+    }
+    if (objectInfo.empty())
+    {
+        BMCWEB_LOG_DEBUG("No updateable software found");
+        // System can exist with no updateable software,
+        // so don't throw error here.
+        return;
+    }
+    asyncResp->res.jsonValue["Updateable"] = true;
+}
+
 /**
  * @brief Updates programmable status of input swId into json response
  *
@@ -354,26 +400,23 @@
     getSwUpdatableStatus(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                          const std::shared_ptr<std::string>& swId)
 {
-    dbus::utility::getAssociationEndPoints(
-        "/xyz/openbmc_project/software/updateable",
-        [asyncResp, swId](const boost::system::error_code& ec,
-                          const dbus::utility::MapperEndPoints& objPaths) {
-        if (ec)
-        {
-            BMCWEB_LOG_DEBUG(" error_code = {} error msg =  {}", ec,
-                             ec.message());
-            // System can exist with no updateable software,
-            // so don't throw error here.
-            return;
-        }
-        std::string reqSwObjPath = "/xyz/openbmc_project/software/" + *swId;
-
-        if (std::ranges::find(objPaths, reqSwObjPath) != objPaths.end())
-        {
-            asyncResp->res.jsonValue["Updateable"] = true;
-            return;
-        }
-    });
+    if constexpr (BMCWEB_REDFISH_UPDATESERVICE_USE_DBUS)
+    {
+        sdbusplus::message::object_path swObjectPath(
+            "/xyz/openbmc_project/software");
+        swObjectPath = swObjectPath / *swId;
+        constexpr std::array<std::string_view, 1> interfaces = {
+            "xyz.openbmc_project.Software.Update"};
+        dbus::utility::getDbusObject(
+            swObjectPath.str, interfaces,
+            std::bind_front(handleUpdateableObject, asyncResp));
+    }
+    else
+    {
+        dbus::utility::getAssociationEndPoints(
+            "/xyz/openbmc_project/software/updateable",
+            std::bind_front(handleUpdateableEndpoints, asyncResp, swId));
+    }
 }
 
 } // namespace sw_util