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
diff --git a/usb/usb_manager.hpp b/usb/usb_manager.hpp
index 98d6796..c7f6403 100644
--- a/usb/usb_manager.hpp
+++ b/usb/usb_manager.hpp
@@ -3,6 +3,7 @@
#include "utils.hpp"
#include <phosphor-logging/lg2.hpp>
+#include <sdbusplus/async.hpp>
#include <sdeventplus/event.hpp>
#include <filesystem>
@@ -24,15 +25,38 @@
USBManager& operator=(const USBManager&) = delete;
USBManager& operator=(USBManager&&) = delete;
+#ifdef START_UPDATE_DBUS_INTEFACE
+
+ explicit USBManager(sdbusplus::async::context& ctx, const fs::path& devPath,
+ const fs::path& usbPath) :
+ ctx(ctx), devicePath(devPath), usbPath(usbPath)
+ {
+ ctx.spawn(run());
+ }
+
+ /** @brief Run the USBManager */
+ auto run() -> sdbusplus::async::task<void>;
+
+ private:
+ /** @brief D-Bus context. */
+ sdbusplus::async::context& ctx;
+
+ /** @brief Starts the firmware update.
+ * @param[in] fd - The file descriptor of the image to update.
+ * @return Success or Fail
+ */
+ auto startUpdate(int fd) -> sdbusplus::async::task<bool>;
+
+#else
explicit USBManager(sdbusplus::bus_t& bus, sdeventplus::Event& event,
const fs::path& devPath, const fs::path& usbPath) :
- bus(bus), event(event), devicePath(devPath), usbPath(usbPath),
- isUSBCodeUpdate(false),
+ bus(bus), event(event), isUSBCodeUpdate(false),
fwUpdateMatcher(bus,
MatchRules::interfacesAdded() +
MatchRules::path("/xyz/openbmc_project/software"),
std::bind(std::mem_fn(&USBManager::updateActivation),
- this, std::placeholders::_1))
+ this, std::placeholders::_1)),
+ devicePath(devPath), usbPath(usbPath)
{
if (!run())
{
@@ -51,6 +75,19 @@
*/
bool run();
+ private:
+ /** @brief Persistent sdbusplus DBus bus connection. */
+ sdbusplus::bus_t& bus;
+
+ /** sd event handler. */
+ sdeventplus::Event& event;
+
+ /** Indicates whether USB codeupdate is going on. */
+ bool isUSBCodeUpdate;
+
+ /** sdbusplus signal match for new image. */
+ sdbusplus::bus::match_t fwUpdateMatcher;
+
/** @brief Creates an Activation D-Bus object.
*
* @param[in] msg - Data associated with subscribed signal
@@ -68,12 +105,14 @@
*/
void setRequestedActivation(const std::string& path);
- private:
- /** @brief Persistent sdbusplus DBus bus connection. */
- sdbusplus::bus_t& bus;
+#endif /* START_UPDATE_DBUS_INTEFACE */
- /** sd event handler. */
- sdeventplus::Event& event;
+ /** @brief Find the first file with a .tar extension according to the USB
+ * file path and copy to IMG_UPLOAD_DIR
+ *
+ * @return Success or Fail
+ */
+ bool copyImage();
/** The USB device path. */
const fs::path& devicePath;
@@ -81,11 +120,8 @@
/** The USB mount path. */
const fs::path& usbPath;
- /** Indicates whether USB codeupdate is going on. */
- bool isUSBCodeUpdate;
-
- /** sdbusplus signal match for new image. */
- sdbusplus::bus::match_t fwUpdateMatcher;
+ /** The destination path for copied over image file */
+ fs::path imageDstPath;
};
} // namespace usb
diff --git a/usb/usb_manager_main.cpp b/usb/usb_manager_main.cpp
index 771b4cd..3f0e5f5 100644
--- a/usb/usb_manager_main.cpp
+++ b/usb/usb_manager_main.cpp
@@ -7,11 +7,6 @@
int main(int argc, char** argv)
{
namespace fs = std::filesystem;
- // Dbus constructs
- auto bus = sdbusplus::bus::new_default();
-
- // Get a default event loop
- auto event = sdeventplus::Event::get_default();
std::string deviceName{};
@@ -21,6 +16,7 @@
CLI11_PARSE(app, argc, argv);
+ // NOLINTNEXTLINE(clang-analyzer-core.uninitialized.UndefReturn)
if (deviceName.empty())
{
lg2::error("The file name passed in is empty.");
@@ -29,11 +25,28 @@
fs::path devicePath = fs::path{"/dev"} / deviceName;
fs::path usbPath = fs::path{"/run/media/usb"} / deviceName;
+
+#ifdef START_UPDATE_DBUS_INTEFACE
+
+ sdbusplus::async::context ctx;
+ phosphor::usb::USBManager manager(ctx, devicePath, usbPath);
+ ctx.run();
+
+#else
+
+ // Dbus constructs
+ auto bus = sdbusplus::bus::new_default();
+
+ // Get a default event loop
+ auto event = sdeventplus::Event::get_default();
+
phosphor::usb::USBManager manager(bus, event, devicePath, usbPath);
// Attach the bus to sd_event to service user requests
bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL);
event.loop();
+#endif // START_UPDATE_DBUS_INTEFACE
+
return 0;
}