fw_update: Introduce FirmwareInventory

Spec reference: [1]

Description:
FirmwareInventory is a class that manages all of the D-Bus
utilities for the firmware update functionality of each entry,
FirmwareInventoryManager is used to manage multiple FirmwareInventory
instances.

Flow of the routine when one or more firmware device is added:
1. When one or more firmware device is added, the InventoryManager
   instance will try to create a FirmwareInventory entry for the added
   device, to accomplish this, it will need to fetch the necessary
   information from various source (e.g. EM, device descriptors).

2. After the information is gathered, the InventoryManager will try to
   obtain a Name for each firmware devices, to fit the different
   platform condition, the name will be reference by the order below:
    1. From Entity Manager (EM), if the endpoint has a specific EM
       configuration with "Name" property listed.
    2. From device descriptors, if the device descriptor contains a
       vendor defined descriptor with "OpenBMC.Name" titled.
    3. Spawn a default one, named "Firmware_Device_<Endpoint ID>".

3. The InventoryManager will then invoke
   `FirmwareInventoryManager::createFirmwareInventory` to create a
   firmware inventory entry.

Properties managed by firmware Inventory:
1. Version
   Version object that represents the firmware version
2. Association
   Association object that represents the associations for the
   firmware

The object path pattern of the firmware inventory entry is:
`/xyz/openbmc_project/software/<BoardName>_<SoftwareName>_<SoftwareID>`

Where:
- `<BoardName>` represents the board the device is on.
- `<SoftwareName>` is the name of the firmware device obtained from the
  InventoryManager.
- `<SoftwareID>` is a 4-byte random number to help consumer
  distinguish from the new/old objects of a inventory item.
  For example:
  `server_board_slot_1_VR_2603`
  The new Activation object and its related interfaces needs to
  resides on a new objectPath, hence the softwareId is appended to
  the path.

Test results:
 - Build passed
 - Successfully create firmware inventory entries
   on Yosemite V4

[1]: https://github.com/openbmc/docs/blob/master/designs/code-update.md

Change-Id: Idebd7d013c82c60f08309a1860d5de1deeb3829a
Signed-off-by: Unive Tien <unive.tien.wiwynn@gmail.com>
Signed-off-by: Carter Chen <carter.chen.wiwynn@gmail.com>
diff --git a/fw-update/inventory_manager.hpp b/fw-update/inventory_manager.hpp
index ade1fcd..673b513 100644
--- a/fw-update/inventory_manager.hpp
+++ b/fw-update/inventory_manager.hpp
@@ -2,6 +2,7 @@
 
 #include "common/instance_id.hpp"
 #include "common/types.hpp"
+#include "firmware_inventory_manager.hpp"
 #include "requester/handler.hpp"
 
 namespace pldm
@@ -41,14 +42,17 @@
      *                                 managed by the BMC.
      */
     explicit InventoryManager(
+        const pldm::utils::DBusHandler* dbusHandler,
         pldm::requester::Handler<pldm::requester::Request>& handler,
         InstanceIdDb& instanceIdDb, DescriptorMap& descriptorMap,
         DownstreamDescriptorMap& downstreamDescriptorMap,
-        ComponentInfoMap& componentInfoMap) :
+        ComponentInfoMap& componentInfoMap,
+        const Configurations& configurations) :
         handler(handler), instanceIdDb(instanceIdDb),
         descriptorMap(descriptorMap),
         downstreamDescriptorMap(downstreamDescriptorMap),
-        componentInfoMap(componentInfoMap)
+        componentInfoMap(componentInfoMap), configurations(configurations),
+        firmwareInventoryManager(dbusHandler, configurations)
     {}
 
     /** @brief Discover the firmware identifiers and component details of FDs
@@ -57,9 +61,18 @@
      *  commands are sent to every FD and the response is used to populate
      *  the firmware identifiers and component details of the FDs.
      *
-     *  @param[in] eids - MCTP endpoint ID of the FDs
+     *  @param[in] mctpInfos - List of MCTP endpoint information
      */
-    void discoverFDs(const std::vector<mctp_eid_t>& eids);
+    void discoverFDs(const MctpInfos& mctpInfos);
+
+    /** @brief Remove the firmware identifiers and component details of FDs
+     *
+     *  This function removes the firmware identifiers, component details and
+     *  downstream device identifiers of the FDs managed by the BMC.
+     *
+     *  @param[in] mctpInfos - List of MCTP endpoint information
+     */
+    void removeFDs(const MctpInfos& mctpInfos);
 
     /** @brief Handler for QueryDeviceIdentifiers command response
      *
@@ -153,6 +166,17 @@
         mctp_eid_t eid, uint32_t dataTransferHandle,
         const enum transfer_op_flag transferOperationFlag);
 
+    /**
+     * @brief obtain Firmware Device Name from either configurations or
+     * descriptors, if none of them is available, a default name is
+     * generated.
+     *
+     * @param[in] eid - Remote MCTP endpoint
+     * @param[in] descriptors - Descriptors of the firmware device
+     */
+    void obtainFirmwareDeviceName(pldm::eid eid,
+                                  const Descriptors& descriptors);
+
     /** @brief Send GetFirmwareParameters command request
      *
      *  @param[in] eid - Remote MCTP endpoint
@@ -168,13 +192,43 @@
     /** @brief Device identifiers of the managed FDs */
     DescriptorMap& descriptorMap;
 
+    /** @brief Firmware Device names of the managed FDs */
+    std::map<eid, SoftwareName> firmwareDeviceNameMap;
+
     /** @brief Downstream Device identifiers of the managed FDs */
     DownstreamDescriptorMap& downstreamDescriptorMap;
 
     /** @brief Component information needed for the update of the managed FDs */
     ComponentInfoMap& componentInfoMap;
+
+    /** @brief Configuration bindings from Entity Manager */
+    const Configurations& configurations;
+
+    /** @brief Dbus Inventory Item Manager */
+    FirmwareInventoryManager firmwareInventoryManager;
 };
 
+/**
+ * @brief Obtain the device name from the configurations
+ *
+ * @param[in] configurations - Configurations from Entity Manager
+ * @param[in] eid - Remote MCTP endpoint
+ *
+ * @return SoftwareName - The Device name, std::nullopt if not found
+ */
+std::optional<SoftwareName> obtainDeviceNameFromConfigurations(
+    const Configurations& configurations, pldm::eid eid);
+
+/**
+ * @brief Obtain the device name from the descriptors
+ *
+ * @param[in] descriptors - Descriptors of the device
+ *
+ * @return SoftwareName - The Device name, std::nullopt if not found
+ */
+std::optional<SoftwareName> obtainDeviceNameFromDescriptors(
+    const Descriptors& descriptors);
+
 } // namespace fw_update
 
 } // namespace pldm