use start update D-Bus interface for usb manager

Use the start update D-Bus interface for usb manager. This change is
based on -
https://gerrit.openbmc.org/c/openbmc/phosphor-dbus-interfaces/+/65738
https://gerrit.openbmc.org/c/openbmc/docs/+/65739

Tested:
```
<6> StartUpdate succeeded, objectPath: /xyz/openbmc_project/software/ce236cf7
```

Change-Id: Ie8337836537d5ca5aca4bcaa0aa86cbd018752eb
Signed-off-by: Jagpal Singh Gill <paligill@gmail.com>
diff --git a/usb/usb_manager.cpp b/usb/usb_manager.cpp
index 226a578..89b0e9b 100644
--- a/usb/usb_manager.cpp
+++ b/usb/usb_manager.cpp
@@ -4,6 +4,10 @@
 
 #include <sys/mount.h>
 
+#include <xyz/openbmc_project/ObjectMapper/client.hpp>
+#include <xyz/openbmc_project/Software/ApplyTime/common.hpp>
+#include <xyz/openbmc_project/Software/Update/client.hpp>
+
 #include <system_error>
 
 namespace phosphor
@@ -11,7 +15,10 @@
 namespace usb
 {
 
-bool USBManager::run()
+using Association = std::tuple<std::string, std::string, std::string>;
+using Paths = std::vector<std::string>;
+
+bool USBManager::copyImage()
 {
     std::error_code ec;
     fs::path dir(usbPath);
@@ -41,6 +48,7 @@
 
             try
             {
+                imageDstPath = dstPath;
                 return fs::copy_file(fs::absolute(p.path()), dstPath);
             }
             catch (const std::exception& e)
@@ -56,6 +64,81 @@
     return false;
 }
 
+#ifdef START_UPDATE_DBUS_INTEFACE
+
+// NOLINTNEXTLINE(readability-static-accessed-through-instance)
+auto findAssociatedUpdatablePath(sdbusplus::async::context& ctx)
+    -> sdbusplus::async::task<Paths>
+{
+    constexpr auto associatedPath =
+        "/xyz/openbmc_project/software/bmc/updateable";
+    constexpr auto interface = "xyz.openbmc_project.Association";
+    constexpr auto propertyName = "endpoints";
+
+    co_return utils::getProperty<Paths>(ctx.get_bus(), associatedPath,
+                                        interface, propertyName);
+}
+
+// NOLINTNEXTLINE(readability-static-accessed-through-instance)
+auto USBManager::startUpdate(int fd) -> sdbusplus::async::task<bool>
+{
+    using Updater = sdbusplus::client::xyz::openbmc_project::software::Update<>;
+    using ApplyTimeIntf =
+        sdbusplus::common::xyz::openbmc_project::software::ApplyTime;
+
+    constexpr auto serviceName = "xyz.openbmc_project.Software.Manager";
+
+    auto paths = co_await findAssociatedUpdatablePath(ctx);
+    if (paths.size() != 1)
+    {
+        lg2::error("Failed to find associated updatable path");
+        co_return false;
+    }
+
+    auto updater = Updater(ctx).service(serviceName).path(paths[0]);
+    sdbusplus::message::object_path objectPath = co_await updater.start_update(
+        fd, ApplyTimeIntf::RequestedApplyTimes::OnReset);
+    if (objectPath.str.empty())
+    {
+        lg2::error("StartUpdate failed");
+        co_return false;
+    }
+    lg2::info("StartUpdate succeeded, objectPath: {PATH}", "PATH", objectPath);
+
+    co_return true;
+}
+
+// NOLINTNEXTLINE(readability-static-accessed-through-instance)
+auto USBManager::run() -> sdbusplus::async::task<void>
+{
+    auto res = copyImage();
+    if (!res)
+    {
+        lg2::error("Failed to copy image from USB");
+        co_return;
+    }
+
+    int fd = open(imageDstPath.c_str(), O_RDONLY);
+    if (fd < 0)
+    {
+        lg2::error("Failed to open {PATH}", "PATH", imageDstPath);
+        co_return;
+    }
+
+    co_await startUpdate(fd);
+
+    ctx.request_stop();
+
+    co_return;
+}
+
+#else
+
+bool USBManager::run()
+{
+    return copyImage();
+}
+
 void USBManager::setApplyTime()
 {
     utils::PropertyValue value =
@@ -130,5 +213,7 @@
     }
 }
 
+#endif // START_UPDATE_DBUS_INTEFACE
+
 } // namespace usb
 } // namespace phosphor