fw_update: Introduce AggregateUpdateManager

Description:
This commit introduces the `AggregateUpdateManager` class for handling
multiple firmware update sessions simultaneously. The
`AggregateUpdateManager` acts as a reverse proxy for PLDM messages,
routing them to the appropriate `UpdateManager` instance based on the
`instanceId`. This allows for concurrent firmware updates, improving
the efficiency and flexibility of the firmware update process.

Motivation:
We have introduced the `FirmwareInventory`/`FirmwareInventoryManager`
classes to manage D-Bus interfaces for firmware update, After that, we
would like to implement the `StartUpdate` method for `FirmwareInventory`
properly for the update process implementation[1], which
`AggregateUpdateManager` will help route the command to the specific
update sessions.

Details of the PLDM message reverse proxy:
By the implementation, different update session would be handled with
different `instanceId`s, which can help `UpdateManager`s to identify
whether the message is for them or not.
Whenever a PLDM response message is received, the flow that
the `AggregateUpdateManager` do:
 1. Handle the message for existing update flow if the instance_id
    (the pldm instance numbers) matches the update task which using the
    existing update flow.
 2. Traverse forward the message to each `ItemUpdateManager`
    (implementation in the next patch) instances if there's no match in
    step 1.
 3. Return error message PLDM_FWUP_COMMAND_NOT_EXPECTED if no matches in
    step 2.

[1]: https://gerrit.openbmc.org/c/openbmc/pldm/+/74774

Change-Id: Icfdb8d238121f9f44a624396e00b378e491ce652
Signed-off-by: Unive Tien <unive.tien.wiwynn@gmail.com>
diff --git a/fw-update/firmware_inventory_manager.cpp b/fw-update/firmware_inventory_manager.cpp
index bb9a6aa..a3e0ac9 100644
--- a/fw-update/firmware_inventory_manager.cpp
+++ b/fw-update/firmware_inventory_manager.cpp
@@ -13,7 +13,7 @@
 void FirmwareInventoryManager::createFirmwareEntry(
     const SoftwareIdentifier& softwareIdentifier,
     const SoftwareName& softwareName, const std::string& activeVersion,
-    const Descriptors& descriptors, const ComponentInfo& componentInfo)
+    const Descriptors& /*descriptors*/, const ComponentInfo& /*componentInfo*/)
 {
     struct timespec ts;
     clock_gettime(CLOCK_REALTIME, &ts);
@@ -42,15 +42,19 @@
                     softwareName, utils::generateSwId());
 
     softwareMap.insert_or_assign(
-        softwareIdentifier, std::make_unique<FirmwareInventory>(
-                                softwareIdentifier, softwarePath, activeVersion,
-                                *boardPath, descriptors, componentInfo));
+        softwareIdentifier,
+        std::make_unique<FirmwareInventory>(softwareIdentifier, softwarePath,
+                                            activeVersion, *boardPath));
 }
 
 void FirmwareInventoryManager::deleteFirmwareEntry(const pldm::eid& eid)
 {
     std::erase_if(softwareMap,
                   [&](const auto& pair) { return pair.first.first == eid; });
+    updateManager.eraseUpdateManagerIf(
+        [&](const SoftwareIdentifier& softwareIdentifier) {
+            return softwareIdentifier.first == eid;
+        });
 }
 
 std::optional<std::filesystem::path> getBoardPath(