fix object manager path and emit interfaces added

- move object manager to the correct path
- setup the bus name in constructor
- emit 'InterfacesAdded' signal for object manager to find our
  software version

Since properties can be uninitialized in the generated bindings,
we have to initialize each property like version and version purpose.

Since object mapper relies on 'InterfacesAdded' signal, emit that
signal such that our version is found in the firmware inventory.

Tested: on Tyan S8030 board with bios code updater

Using dbus-monitor, verify that the signal was emitted for initial
version.

```
dbus-monitor --system "sender='xyz.openbmc_project.Software.BIOS',member='InterfacesAdded'"

signal time=1740740306.586571 sender=:1.266 -> destination=(null destination) serial=21 path=/xyz/openbmc_project/software; interface=org.freedesktop.DBus.ObjectManager; member=InterfacesAdded
   object path "/xyz/openbmc_project/software/HostSPIFlash_1520"
   array [
      dict entry(
         string "xyz.openbmc_project.Software.Version"
         array [
            dict entry(
               string "Version"
               variant                   string "v1.03"
            )
            dict entry(
               string "Purpose"
               variant                   string "xyz.openbmc_project.Software.Version.VersionPurpose.Other"
            )
         ]
      )
   ]
```

Using object mapper, verify that it has picked up our initial version:

```
busctl call xyz.openbmc_project.ObjectMapper /xyz/openbmc_project/object_mapper xyz.openbmc_project.ObjectMapper GetSubTree sias /xyz/openbmc_project/ 0 1 xyz.openbmc_project.Software.Version
```

Not showing output here since it gets verbose.

Checking the firmware inventory, the version also shows up:
```
{
  "@odata.id": "/redfish/v1/UpdateService/FirmwareInventory",
  "@odata.type": "#SoftwareInventoryCollection.SoftwareInventoryCollection",
  "Members": [
    {
      "@odata.id": "/redfish/v1/UpdateService/FirmwareInventory/5e6297dd"
    },
    {
      "@odata.id": "/redfish/v1/UpdateService/FirmwareInventory/HostSPIFlash_1520"
    },
    {
      "@odata.id": "/redfish/v1/UpdateService/FirmwareInventory/bios_active"
    }
  ],
  "Members@odata.count": 3,
  "Name": "Software Inventory Collection"
}
```

Checking the specific entry:
```
curl  $creds https://$bmc/redfish/v1/UpdateService/FirmwareInventory/HostSPIFlash_1520
{
  "@odata.id": "/redfish/v1/UpdateService/FirmwareInventory/HostSPIFlash_1520",
  "@odata.type": "#SoftwareInventory.v1_1_0.SoftwareInventory",
  "Description": "Other image",
  "Id": "HostSPIFlash_1520",
  "Name": "Software Inventory",
  "Status": {
    "Health": "Warning",
    "HealthRollup": "OK",
    "State": "Disabled"
  },
  "Updateable": false,
  "Version": "v1.03"
}
```

Now, running an update:

```
curl -k --insecure --user root:root -H Content-Type:multipart/form-data -X POST -F 'UpdateParameters={"Targets":["/redfish/v1/UpdateService/FirmwareInventory/HostSPIFlash_1520"],"@Redfish.OperationApplyTime":"Immediate"};type=application/json' -F 'UpdateFile=@pldm-package.bin;type=application/octet-stream' https://${bmc}/redfish/v1/UpdateService/update
{
  "@odata.id": "/redfish/v1/TaskService/Tasks/0",
  "@odata.type": "#Task.v1_4_3.Task",
  "Id": "0",
  "TaskState": "Running",
  "TaskStatus": "OK"
}
```

Checking the task status:
```
curl --silent --insecure --user root:root https://${bmc}/redfish/v1/TaskService/Tasks/0
{
  "@odata.id": "/redfish/v1/TaskService/Tasks/0",
  "@odata.type": "#Task.v1_4_3.Task",
  "EndTime": "2025-02-28T11:10:55+00:00",
  "HidePayload": false,
  "Id": "0",
  "Messages": [
    {
      "@odata.type": "#Message.v1_1_1.Message",
      "Message": "The task with Id '0' has started.",
      "MessageArgs": [
        "0"
      ],
      "MessageId": "TaskEvent.1.0.TaskStarted",
      "MessageSeverity": "OK",
      "Resolution": "None."
    },
    {
      "@odata.type": "#Message.v1_1_1.Message",
      "Message": "The task with Id '0' has changed to progress 10 percent complete.",
      "MessageArgs": [
        "0",
        "10"
      ],
      "MessageId": "TaskEvent.1.0.TaskProgressChanged",
      "MessageSeverity": "OK",
      "Resolution": "None."
    },
    {
      "@odata.type": "#Message.v1_1_1.Message",
      "Message": "The task with Id '0' has changed to progress 20 percent complete.",
      "MessageArgs": [
        "0",
        "20"
      ],
      "MessageId": "TaskEvent.1.0.TaskProgressChanged",
      "MessageSeverity": "OK",
      "Resolution": "None."
    },
    {
      "@odata.type": "#Message.v1_1_1.Message",
      "Message": "The task with Id '0' has changed to progress 70 percent complete.",
      "MessageArgs": [
        "0",
        "70"
      ],
      "MessageId": "TaskEvent.1.0.TaskProgressChanged",
      "MessageSeverity": "OK",
      "Resolution": "None."
    },
    {
      "@odata.type": "#Message.v1_1_1.Message",
      "Message": "The task with Id '0' has changed to progress 100 percent complete.",
      "MessageArgs": [
        "0",
        "100"
      ],
      "MessageId": "TaskEvent.1.0.TaskProgressChanged",
      "MessageSeverity": "OK",
      "Resolution": "None."
    },
    {
      "@odata.type": "#Message.v1_1_1.Message",
      "Message": "The task with Id '0' has completed.",
      "MessageArgs": [
        "0"
      ],
      "MessageId": "TaskEvent.1.0.TaskCompletedOK",
      "MessageSeverity": "OK",
      "Resolution": "None."
    }
  ],
  "Name": "Task 0",
  "Payload": {
    "HttpHeaders": [],
    "HttpOperation": "POST",
    "JsonBody": "null",
    "TargetUri": "/redfish/v1/UpdateService/update"
  },
  "PercentComplete": 100,
  "StartTime": "2025-02-28T11:10:28+00:00",
  "TaskMonitor": "/redfish/v1/TaskService/TaskMonitors/0",
  "TaskState": "Completed",
  "TaskStatus": "OK"
}
```

Successfully applied this update and the firmware inventory is changed
as expected

```
{
  "@odata.id": "/redfish/v1/UpdateService/FirmwareInventory",
  "@odata.type": "#SoftwareInventoryCollection.SoftwareInventoryCollection",
  "Members": [
    {
      "@odata.id": "/redfish/v1/UpdateService/FirmwareInventory/5e6297dd"
    },
    {
      "@odata.id": "/redfish/v1/UpdateService/FirmwareInventory/HostSPIFlash_1149"
    },
    {
      "@odata.id": "/redfish/v1/UpdateService/FirmwareInventory/bios_active"
    }
  ],
  "Members@odata.count": 3,
  "Name": "Software Inventory Collection"
}
```

Checking the object mapper, it is also aware of the new version.

Change-Id: If45158be3ae486e94ae2feb37ce8163b5f795054
Signed-off-by: Alexander Hansen <alexander.hansen@9elements.com>
diff --git a/common/include/software.hpp b/common/include/software.hpp
index 09a0b0f..d3e8ffc 100644
--- a/common/include/software.hpp
+++ b/common/include/software.hpp
@@ -8,6 +8,7 @@
 #include <xyz/openbmc_project/Software/ActivationBlocksTransition/aserver.hpp>
 #include <xyz/openbmc_project/Software/ActivationProgress/aserver.hpp>
 #include <xyz/openbmc_project/Software/Version/aserver.hpp>
+#include <xyz/openbmc_project/Software/Version/client.hpp>
 
 #include <string>
 
@@ -65,8 +66,14 @@
     void enableUpdate(const std::set<RequestedApplyTimes>& allowedApplyTimes);
 
     // This should populate 'softwareVersion'
-    // @param version      the version string
-    void setVersion(const std::string& versionStr);
+    // @param version         the version string
+    // @param versionPurpose  which kind of software
+    void setVersion(const std::string& versionStr,
+                    SoftwareVersion::VersionPurpose versionPurpose =
+                        SoftwareVersion::VersionPurpose::Unknown);
+
+    // Return the version purpose
+    SoftwareVersion::VersionPurpose getPurpose();
 
     // This should populate 'softwareAssociationDefinitions'
     // @param isRunning             if the software version is currently running
diff --git a/common/include/software_manager.hpp b/common/include/software_manager.hpp
index 7cc2e6a..1e0a427 100644
--- a/common/include/software_manager.hpp
+++ b/common/include/software_manager.hpp
@@ -53,11 +53,6 @@
     sdbusplus::async::context& ctx;
 
   private:
-    // request the bus name on dbus after all configuration has been parsed
-    // and the devices have been initialized
-    // @returns        the name on dbus
-    std::string setupBusName();
-
     // this is appended to the common prefix to construct the dbus name
     std::string serviceNameSuffix;
 
diff --git a/common/src/device.cpp b/common/src/device.cpp
index 2367213..9e2278d 100644
--- a/common/src/device.cpp
+++ b/common/src/device.cpp
@@ -164,7 +164,8 @@
 {
     softwarePending->setActivation(ActivationInterface::Activations::Ready);
 
-    softwarePending->setVersion(componentVersion);
+    softwarePending->setVersion(componentVersion,
+                                softwareCurrent->getPurpose());
 
     std::string objPath = softwarePending->objectPath;
 
diff --git a/common/src/software.cpp b/common/src/software.cpp
index faa377a..31b2b75 100644
--- a/common/src/software.cpp
+++ b/common/src/software.cpp
@@ -123,10 +123,13 @@
     co_return;
 }
 
-void Software::setVersion(const std::string& versionStr)
+void Software::setVersion(const std::string& versionStr,
+                          SoftwareVersion::VersionPurpose versionPurpose)
 {
     debug("{SWID}: set version {VERSION}", "SWID", swid, "VERSION", versionStr);
 
+    const bool emitSignal = !version;
+
     if (!version)
     {
         version =
@@ -134,6 +137,17 @@
     }
 
     version->version(versionStr);
+    version->purpose(versionPurpose);
+
+    if (emitSignal)
+    {
+        version->emit_added();
+    }
+}
+
+SoftwareVersion::VersionPurpose Software::getPurpose()
+{
+    return version->purpose();
 }
 
 void Software::setActivationBlocksTransition(bool enabled)
diff --git a/common/src/software_manager.cpp b/common/src/software_manager.cpp
index b95fcab..77ee0b1 100644
--- a/common/src/software_manager.cpp
+++ b/common/src/software_manager.cpp
@@ -7,6 +7,7 @@
 #include <sdbusplus/bus.hpp>
 #include <xyz/openbmc_project/Association/Definitions/server.hpp>
 #include <xyz/openbmc_project/ObjectMapper/client.hpp>
+#include <xyz/openbmc_project/Software/Version/client.hpp>
 #include <xyz/openbmc_project/State/Host/client.hpp>
 
 #include <cstdint>
@@ -17,21 +18,18 @@
 
 SoftwareManager::SoftwareManager(sdbusplus::async::context& ctx,
                                  const std::string& serviceNameSuffix) :
-    ctx(ctx), serviceNameSuffix(serviceNameSuffix), manager(ctx, "/")
-{
-    debug("initialized SoftwareManager");
-}
-
-std::string SoftwareManager::setupBusName()
+    ctx(ctx), serviceNameSuffix(serviceNameSuffix),
+    manager(ctx, sdbusplus::client::xyz::openbmc_project::software::Version<>::
+                     namespace_path)
 {
     const std::string serviceNameFull =
         "xyz.openbmc_project.Software." + serviceNameSuffix;
 
     debug("requesting dbus name {BUSNAME}", "BUSNAME", serviceNameFull);
 
-    ctx.get_bus().request_name(serviceNameFull.c_str());
+    ctx.request_name(serviceNameFull.c_str());
 
-    return serviceNameFull;
+    debug("Initialized SoftwareManager");
 }
 
 // NOLINTBEGIN(readability-static-accessed-through-instance)
@@ -133,6 +131,4 @@
     }
 
     debug("[config] done with initial configuration");
-
-    setupBusName();
 }