fw-update: Add StartUpdate D-Bus API support for firmware updates

This commit adds support for the StartUpdate D-Bus API to enable FW
updates through the xyz.openbmc_project.Software.Update interface. The
user would need to enable `fw-update-pkg-inotify` meson option to
switch to inotify mechanism.

The existing inotify mechanism has critical limitations:
- Race condition between a BMC code updater and PLDM updater when
  accessing images from /tmp/images directory
- Lack of a standard D-Bus interface for firmware operations
- No proper error handling or status reporting

This implementation follows the upstream design for device & component
level inventory & update, based on the proposed code-update design
document [1]. The FW Update is triggered at the top-level i.e. all valid
targets will be updated with a single StartUpdate call.

Key changes:
- Add Update class implementing the Software.Update D-Bus interface
- Add startUpdate method that accepts file descriptors and processes
  firmware packages via streams
- Refactor UpdateManager to support both file path and stream-based
  package processing

Tests:
- Successful FW Update with both inotify and startUpdate flows on
  gb200nvl-obmc platform with multiple components (GPU + SMA)
- FW Update failure case by modifying the package size. The Redfish task
  immediately fails with Exception after creation.

[1]: https://gerrit.openbmc.org/c/openbmc/docs/+/76645

Change-Id: Ic2ca74431316161de844f6a3966f612760f5c298
Signed-off-by: P Arun Kumar Reddy <arunpapannagari23@gmail.com>
diff --git a/meson.build b/meson.build
index 461d657..9b5b00b 100644
--- a/meson.build
+++ b/meson.build
@@ -142,6 +142,11 @@
 conf_data.set('SENSOR_POLLING_TIME', get_option('sensor-polling-time'))
 conf_data.set('UPDATE_TIMEOUT_SECONDS', get_option('update-timeout-seconds'))
 
+# Firmware update inotify option
+if get_option('fw-update-pkg-inotify').allowed()
+    conf_data.set('FW_UPDATE_INOTIFY_ENABLED', 1)
+endif
+
 configure_file(output: 'config.h', configuration: conf_data)
 
 add_project_arguments(
@@ -242,18 +247,26 @@
     deps += [libpldmresponder_dep]
 endif
 
-executable(
-    'pldmd',
-    'pldmd/pldmd.cpp',
-    'pldmd/dbus_impl_pdr.cpp',
+fw_update_sources = [
     'fw-update/activation.cpp',
     'fw-update/inventory_manager.cpp',
     'fw-update/firmware_inventory_manager.cpp',
     'fw-update/firmware_inventory.cpp',
     'fw-update/package_parser.cpp',
     'fw-update/device_updater.cpp',
-    'fw-update/watch.cpp',
     'fw-update/update_manager.cpp',
+    'fw-update/update.cpp',
+]
+
+if get_option('fw-update-pkg-inotify').allowed()
+    fw_update_sources += 'fw-update/watch.cpp'
+endif
+
+executable(
+    'pldmd',
+    'pldmd/pldmd.cpp',
+    'pldmd/dbus_impl_pdr.cpp',
+    fw_update_sources,
     'platform-mc/dbus_impl_fru.cpp',
     'platform-mc/terminus_manager.cpp',
     'platform-mc/terminus.cpp',