libpldmresponder: enable DBus change notification

This commit enables libpldmresponder to subscribe to DBus
property change signal for the BIOS properties which are fetched from
DBus. The new DBus value is received and the relevant entry in the
attributeValueTable is updated.

test result:

root@rainier:/tmp# pldmtool bios GetBIOSTable -t 0
Parsed Response Msg:
PLDM StringTable:
BIOSStringHandle : BIOSString
0 : Allowed
1 : Disabled
2 : Enabled
3 : IPv4DHCP
4 : IPv4Static
5 : Not Allowed
6 : Perm
7 : Temp
8 : pvm-fw-boot-side
9 : pvm-inband-code-update
10 : pvm-os-boot-side
11 : pvm-pcie-error-inject
12 : pvm-surveillance
13 : pvm-system-name
14 : vmi-hostname
15 : vmi-if-count
16 : vmi-if0-ipv4-ipaddr
17 : vmi-if0-ipv4-method
18 : vmi-if0-ipv4-prefix-length
19 : vmi-if1-ipv4-ipaddr
20 : vmi-if1-ipv4-method
21 : vmi-if1-ipv4-prefix-length
22 : vmi-ipv4-gateway
root@rainier:/tmp#

root@rainier:/tmp# pldmtool bios GetBIOSTable -t 1
Parsed Response Msg:
PLDM AttributeTable:
AttributeHandle: 0, AttributeNameHandle: 13(pvm-system-name)
        AttributeType: BIOSStringReadOnly
        StringType: 0x01
        MinimumStringLength: 1
        MaximumStringLength: 100
        DefaultStringLength: 15
        DefaultString: witherspoon-128
AttributeHandle: 1, AttributeNameHandle: 14(vmi-hostname)
        AttributeType: BIOSString
        StringType: 0x01
        MinimumStringLength: 0
        MaximumStringLength: 255
        DefaultStringLength: 0
        DefaultString:
AttributeHandle: 2, AttributeNameHandle: 22(vmi-ipv4-gateway)
        AttributeType: BIOSString
        StringType: 0x01
        MinimumStringLength: 7
        MaximumStringLength: 15
        DefaultStringLength: 7
        DefaultString: 0.0.0.0
AttributeHandle: 3, AttributeNameHandle: 16(vmi-if0-ipv4-ipaddr)
        AttributeType: BIOSString
        StringType: 0x01
        MinimumStringLength: 7
        MaximumStringLength: 15
        DefaultStringLength: 7
        DefaultString: 0.0.0.0
AttributeHandle: 4, AttributeNameHandle: 19(vmi-if1-ipv4-ipaddr)
        AttributeType: BIOSString
        StringType: 0x01
        MinimumStringLength: 7
        MaximumStringLength: 15
        DefaultStringLength: 7
        DefaultString: 0.0.0.0
AttributeHandle: 5, AttributeNameHandle: 15(vmi-if-count)
        AttributeType: BIOSIntegerReadOnly
        LowerBound: 0
        UpperBound: 2
        ScalarIncrement: 1
        DefaultValue: 1
AttributeHandle: 6, AttributeNameHandle: 18(vmi-if0-ipv4-prefix-length)
        AttributeType: BIOSInteger
        LowerBound: 0
        UpperBound: 32
        ScalarIncrement: 1
        DefaultValue: 0
AttributeHandle: 7, AttributeNameHandle: 21(vmi-if1-ipv4-prefix-length)
        AttributeType: BIOSInteger
        LowerBound: 0
        UpperBound: 32
        ScalarIncrement: 1
        DefaultValue: 0
AttributeHandle: 8, AttributeNameHandle: 8(pvm-fw-boot-side)
        AttributeType: BIOSEnumerationReadOnly
        NumberOfPossibleValues: 2
                PossibleValueStringHandle[0] = 6(Perm)
                PossibleValueStringHandle[1] = 7(Temp)
        NumberOfDefaultValues: 1
                DefaultValueStringHandleIndex[0] = 0, StringHandle = 6(Perm)
AttributeHandle: 9, AttributeNameHandle: 10(pvm-os-boot-side)
        AttributeType: BIOSEnumerationReadOnly
        NumberOfPossibleValues: 2
                PossibleValueStringHandle[0] = 6(Perm)
                PossibleValueStringHandle[1] = 7(Temp)
        NumberOfDefaultValues: 1
                DefaultValueStringHandleIndex[0] = 0, StringHandle = 6(Perm)
AttributeHandle: 10, AttributeNameHandle: 9(pvm-inband-code-update)
        AttributeType: BIOSEnumerationReadOnly
        NumberOfPossibleValues: 2
                PossibleValueStringHandle[0] = 0(Allowed)
                PossibleValueStringHandle[1] = 5(Not Allowed)
        NumberOfDefaultValues: 1
                DefaultValueStringHandleIndex[0] = 0, StringHandle = 0(Allowed)
AttributeHandle: 11, AttributeNameHandle: 12(pvm-surveillance)
        AttributeType: BIOSEnumerationReadOnly
        NumberOfPossibleValues: 2
                PossibleValueStringHandle[0] = 1(Disabled)
                PossibleValueStringHandle[1] = 2(Enabled)
        NumberOfDefaultValues: 1
                DefaultValueStringHandleIndex[0] = 1, StringHandle = 2(Enabled)
AttributeHandle: 12, AttributeNameHandle: 11(pvm-pcie-error-inject)
        AttributeType: BIOSEnumerationReadOnly
        NumberOfPossibleValues: 2
                PossibleValueStringHandle[0] = 1(Disabled)
                PossibleValueStringHandle[1] = 2(Enabled)
        NumberOfDefaultValues: 1
                DefaultValueStringHandleIndex[0] = 1, StringHandle = 2(Enabled)
AttributeHandle: 13, AttributeNameHandle: 17(vmi-if0-ipv4-method)
        AttributeType: BIOSEnumeration
        NumberOfPossibleValues: 2
                PossibleValueStringHandle[0] = 4(IPv4Static)
                PossibleValueStringHandle[1] = 3(IPv4DHCP)
        NumberOfDefaultValues: 1
                DefaultValueStringHandleIndex[0] = 0, StringHandle = 4(IPv4Static)
AttributeHandle: 14, AttributeNameHandle: 20(vmi-if1-ipv4-method)
        AttributeType: BIOSEnumeration
        NumberOfPossibleValues: 2
                PossibleValueStringHandle[0] = 4(IPv4Static)
                PossibleValueStringHandle[1] = 3(IPv4DHCP)
        NumberOfDefaultValues: 1
                DefaultValueStringHandleIndex[0] = 0, StringHandle = 4(IPv4Static)
root@rainier:/tmp#

root@rainier:/tmp# pldmtool bios GetBIOSTable -t 2
Parsed Response Msg:
PLDM AttributeValueTable:
AttributeHandle: 0
        AttributeType: BIOSStringReadOnly
        CurrentStringLength: 15
        CurrentString: witherspoon-128
AttributeHandle: 1
        AttributeType: BIOSString
        CurrentStringLength: 0
        CurrentString:
AttributeHandle: 2
        AttributeType: BIOSString
        CurrentStringLength: 7
        CurrentString: 0.0.0.0
AttributeHandle: 3
        AttributeType: BIOSString
        CurrentStringLength: 7
        CurrentString: 0.0.0.0
AttributeHandle: 4
        AttributeType: BIOSString
        CurrentStringLength: 7
        CurrentString: 0.0.0.0
AttributeHandle: 5
        AttributeType: BIOSIntegerReadOnly
        CurrentValue: 1
AttributeHandle: 6
        AttributeType: BIOSInteger
        CurrentValue: 0
AttributeHandle: 7
        AttributeType: BIOSInteger
        CurrentValue: 0
AttributeHandle: 8
        AttributeType: BIOSEnumerationReadOnly
        NumberOfCurrentValues: 1
        CurrentValueStringHandleIndex[0] = 0, StringHandle = 6(Perm)
AttributeHandle: 9
        AttributeType: BIOSEnumerationReadOnly
        NumberOfCurrentValues: 1
        CurrentValueStringHandleIndex[0] = 0, StringHandle = 6(Perm)
AttributeHandle: 10
        AttributeType: BIOSEnumerationReadOnly
        NumberOfCurrentValues: 1
        CurrentValueStringHandleIndex[0] = 0, StringHandle = 0(Allowed)
AttributeHandle: 11
        AttributeType: BIOSEnumerationReadOnly
        NumberOfCurrentValues: 1
        CurrentValueStringHandleIndex[0] = 1, StringHandle = 2(Enabled)
AttributeHandle: 12
        AttributeType: BIOSEnumerationReadOnly
        NumberOfCurrentValues: 1
        CurrentValueStringHandleIndex[0] = 1, StringHandle = 2(Enabled)
AttributeHandle: 13
        AttributeType: BIOSEnumeration
        NumberOfCurrentValues: 1
        CurrentValueStringHandleIndex[0] = 0, StringHandle = 4(IPv4Static)
AttributeHandle: 14
        AttributeType: BIOSEnumeration
        NumberOfCurrentValues: 1
        CurrentValueStringHandleIndex[0] = 0, StringHandle = 4(IPv4Static)
root@rainier:/tmp#

root@rainier:/tmp# busctl get-property  xyz.openbmc_project.Settings
/xyz/openbmc_project/network/vmi/intf1/ipv4/addr0 xyz.openbmc_project.Network.IP
PrefixLength
y 0

root@rainier:/tmp# busctl set-property  xyz.openbmc_project.Settings
/xyz/openbmc_project/network/vmi/intf1/ipv4/addr0 xyz.openbmc_project.Network.IP
PrefixLength y 6

root@rainier:/tmp# busctl get-property  xyz.openbmc_project.Settings
/xyz/openbmc_project/network/vmi/intf1/ipv4/addr0 xyz.openbmc_project.Network.IP
Origin
s "xyz.openbmc_project.Network.IP.AddressOrigin.Static"

root@rainier:/tmp# busctl set-property  xyz.openbmc_project.Settings
/xyz/openbmc_project/network/vmi/intf1/ipv4/addr0 xyz.openbmc_project.Network.IP
Origin s "xyz.openbmc_project.Network.IP.AddressOrigin.DHCP"

root@rainier:/tmp# busctl get-property  xyz.openbmc_project.Settings
/xyz/openbmc_project/network/vmi/intf1/ipv4/addr0 xyz.openbmc_project.Network.IP
Address
s "0.0.0.0"

root@rainier:/tmp# busctl set-property  xyz.openbmc_project.Settings
/xyz/openbmc_project/network/vmi/intf1/ipv4/addr0 xyz.openbmc_project.Network.IP
Address s "1.2.3.4"

root@rainier:/tmp# pldmtool bios GetBIOSTable -t 2
Parsed Response Msg:
PLDM AttributeValueTable:
AttributeHandle: 0
        AttributeType: BIOSStringReadOnly
        CurrentStringLength: 15
        CurrentString: witherspoon-128
AttributeHandle: 1
        AttributeType: BIOSString
        CurrentStringLength: 0
        CurrentString:
AttributeHandle: 2
        AttributeType: BIOSString
        CurrentStringLength: 7
        CurrentString: 0.0.0.0
AttributeHandle: 3
        AttributeType: BIOSString
        CurrentStringLength: 7
        CurrentString: 0.0.0.0
AttributeHandle: 4
        AttributeType: BIOSString
        CurrentStringLength: 7
        CurrentString: 1.2.3.4
AttributeHandle: 5
        AttributeType: BIOSIntegerReadOnly
        CurrentValue: 1
AttributeHandle: 6
        AttributeType: BIOSInteger
        CurrentValue: 0
AttributeHandle: 7
        AttributeType: BIOSInteger
        CurrentValue: 6
AttributeHandle: 8
        AttributeType: BIOSEnumerationReadOnly
        NumberOfCurrentValues: 1
        CurrentValueStringHandleIndex[0] = 0, StringHandle = 6(Perm)
AttributeHandle: 9
        AttributeType: BIOSEnumerationReadOnly
        NumberOfCurrentValues: 1
        CurrentValueStringHandleIndex[0] = 0, StringHandle = 6(Perm)
AttributeHandle: 10
        AttributeType: BIOSEnumerationReadOnly
        NumberOfCurrentValues: 1
        CurrentValueStringHandleIndex[0] = 0, StringHandle = 0(Allowed)
AttributeHandle: 11
        AttributeType: BIOSEnumerationReadOnly
        NumberOfCurrentValues: 1
        CurrentValueStringHandleIndex[0] = 1, StringHandle = 2(Enabled)
AttributeHandle: 12
        AttributeType: BIOSEnumerationReadOnly
        NumberOfCurrentValues: 1
        CurrentValueStringHandleIndex[0] = 1, StringHandle = 2(Enabled)
AttributeHandle: 13
        AttributeType: BIOSEnumeration
        NumberOfCurrentValues: 1
        CurrentValueStringHandleIndex[0] = 0, StringHandle = 4(IPv4Static)
AttributeHandle: 14
        AttributeType: BIOSEnumeration
        NumberOfCurrentValues: 1
        CurrentValueStringHandleIndex[0] = 1, StringHandle = 3(IPv4DHCP)

Change-Id: I60e8f916a82bda0ef27c8c482fafb755b65210b4
Signed-off-by: Sampa Misra <sampmisr@in.ibm.com>
diff --git a/libpldmresponder/bios_attribute.cpp b/libpldmresponder/bios_attribute.cpp
index a998b53..f6b3912 100644
--- a/libpldmresponder/bios_attribute.cpp
+++ b/libpldmresponder/bios_attribute.cpp
@@ -1,5 +1,8 @@
+#include "config.h"
+
 #include "bios_attribute.hpp"
 
+#include "bios_config.hpp"
 #include "utils.hpp"
 
 #include <iostream>
@@ -28,6 +31,11 @@
     }
 }
 
+std::optional<DBusMapping> BIOSAttribute::getDBusMap()
+{
+    return dBusMap;
+}
+
 } // namespace bios
 } // namespace responder
 } // namespace pldm
diff --git a/libpldmresponder/bios_attribute.hpp b/libpldmresponder/bios_attribute.hpp
index d63b331..3f3ab4d 100644
--- a/libpldmresponder/bios_attribute.hpp
+++ b/libpldmresponder/bios_attribute.hpp
@@ -60,6 +60,21 @@
     virtual void constructEntry(const BIOSStringTable& stringTable,
                                 Table& attrTable, Table& attrValueTable) = 0;
 
+    /** @brief Method to update the value for an attribute
+     *  @param[in,out] newValue - An attribute value table row with the new
+     * value for the attribute
+     *  @param[in] attrHdl - attribute handle
+     *  @param[in] attrType - attribute type
+     *  @param[in] newPropVal - The new value
+     *  @return PLDM Success or failure status
+     */
+    virtual int updateAttrVal(Table& newValue, uint16_t attrHdl,
+                              uint8_t attrType,
+                              const PropertyValue& newPropVal) = 0;
+
+    /** @brief Method to return the D-Bus map */
+    std::optional<DBusMapping> getDBusMap();
+
     /** @brief Name of this attribute */
     const std::string name;
 
@@ -76,4 +91,4 @@
 
 } // namespace bios
 } // namespace responder
-} // namespace pldm
\ No newline at end of file
+} // namespace pldm
diff --git a/libpldmresponder/bios_config.cpp b/libpldmresponder/bios_config.cpp
index e742ee6..ade09b2 100644
--- a/libpldmresponder/bios_config.cpp
+++ b/libpldmresponder/bios_config.cpp
@@ -3,6 +3,7 @@
 #include "bios_enum_attribute.hpp"
 #include "bios_integer_attribute.hpp"
 #include "bios_string_attribute.hpp"
+#include "bios_table.hpp"
 
 #include <fstream>
 #include <iostream>
@@ -263,6 +264,83 @@
     }
 }
 
+void BIOSConfig::processBiosAttrChangeNotification(
+    const DbusChObjProperties& chProperties, uint32_t biosAttrIndex)
+{
+    const auto& dBusMap = biosAttributes[biosAttrIndex]->getDBusMap();
+    const auto& propertyName = dBusMap->propertyName;
+    const auto& attrName = biosAttributes[biosAttrIndex]->name;
+
+    const auto it = chProperties.find(propertyName);
+    if (it == chProperties.end())
+    {
+        return;
+    }
+
+    PropertyValue newPropVal = it->second;
+    auto stringTable = getBIOSTable(PLDM_BIOS_STRING_TABLE);
+    if (!stringTable.has_value())
+    {
+        std::cerr << "BIOS string table unavailable\n";
+        return;
+    }
+    BIOSStringTable biosStringTable(*stringTable);
+    uint16_t attrNameHdl{};
+    try
+    {
+        attrNameHdl = biosStringTable.findHandle(attrName);
+    }
+    catch (std::invalid_argument& e)
+    {
+        std::cerr << "Could not find handle for BIOS string, ATTRIBUTE="
+                  << attrName.c_str() << "\n";
+        return;
+    }
+
+    auto attrTable = getBIOSTable(PLDM_BIOS_ATTR_TABLE);
+    if (!attrTable.has_value())
+    {
+        std::cerr << "Attribute table not present\n";
+        return;
+    }
+    const struct pldm_bios_attr_table_entry* tableEntry =
+        table::attribute::findByStringHandle(*attrTable, attrNameHdl);
+    if (tableEntry == nullptr)
+    {
+        std::cerr << "Attribute not found in attribute table, name= "
+                  << attrName.c_str() << "name handle=" << attrNameHdl << "\n";
+        return;
+    }
+
+    auto [attrHdl, attrType, stringHdl] =
+        table::attribute::decodeHeader(tableEntry);
+
+    auto attrValueSrcTable = getBIOSTable(PLDM_BIOS_ATTR_VAL_TABLE);
+
+    if (!attrValueSrcTable.has_value())
+    {
+        std::cerr << "Attribute value table not present\n";
+        return;
+    }
+
+    Table newValue;
+    auto rc = biosAttributes[biosAttrIndex]->updateAttrVal(
+        newValue, attrHdl, attrType, newPropVal);
+    if (rc != PLDM_SUCCESS)
+    {
+        std::cerr << "Could not update the attribute value table for attribute "
+                     "handle="
+                  << attrHdl << " and type=" << (uint32_t)attrType << "\n";
+        return;
+    }
+    auto destTable = table::attribute_value::updateTable(
+        *attrValueSrcTable, newValue.data(), newValue.size());
+    if (destTable.has_value())
+    {
+        storeTable(tableDir / attrValueTableFile, *destTable);
+    }
+}
+
 } // namespace bios
 } // namespace responder
 } // namespace pldm
diff --git a/libpldmresponder/bios_config.hpp b/libpldmresponder/bios_config.hpp
index dd892b1..ae1794e 100644
--- a/libpldmresponder/bios_config.hpp
+++ b/libpldmresponder/bios_config.hpp
@@ -70,6 +70,22 @@
     using BIOSAttributes = std::vector<std::unique_ptr<BIOSAttribute>>;
     BIOSAttributes biosAttributes;
 
+    using propName = std::string;
+    using DbusChObjProperties = std::map<propName, PropertyValue>;
+
+    // vector to catch the D-Bus property change signals for BIOS attributes
+    std::vector<std::unique_ptr<sdbusplus::bus::match::match>> biosAttrMatch;
+
+    /** @brief Method to update a BIOS attribute when the corresponding Dbus
+     *  property is changed
+     *  @param[in] chProperties - list of properties which have changed
+     *  @param[in] biosAttrIndex - Index of BIOSAttribute pointer in
+     * biosAttributes
+     *  @return - none
+     */
+    void processBiosAttrChangeNotification(
+        const DbusChObjProperties& chProperties, uint32_t biosAttrIndex);
+
     /** @brief Construct an attribute and persist it
      *  @tparam T - attribute type
      *  @param[in] entry - json entry
@@ -80,6 +96,26 @@
         try
         {
             biosAttributes.push_back(std::make_unique<T>(entry, dbusHandler));
+            auto biosAttrIndex = biosAttributes.size() - 1;
+            auto dBusMap = biosAttributes[biosAttrIndex]->getDBusMap();
+
+            if (dBusMap.has_value())
+            {
+                using namespace sdbusplus::bus::match::rules;
+                biosAttrMatch.push_back(
+                    std::make_unique<sdbusplus::bus::match::match>(
+                        pldm::utils::DBusHandler::getBus(),
+                        propertiesChanged(dBusMap->objectPath,
+                                          dBusMap->interface),
+                        [this,
+                         biosAttrIndex](sdbusplus::message::message& msg) {
+                            DbusChObjProperties props;
+                            std::string iface;
+                            msg.read(iface, props);
+                            processBiosAttrChangeNotification(props,
+                                                              biosAttrIndex);
+                        }));
+            }
         }
         catch (const std::exception& e)
         {
@@ -124,4 +160,4 @@
 
 } // namespace bios
 } // namespace responder
-} // namespace pldm
\ No newline at end of file
+} // namespace pldm
diff --git a/libpldmresponder/bios_enum_attribute.cpp b/libpldmresponder/bios_enum_attribute.cpp
index 7d7cba4..2f7da62 100644
--- a/libpldmresponder/bios_enum_attribute.cpp
+++ b/libpldmresponder/bios_enum_attribute.cpp
@@ -1,3 +1,5 @@
+#include "config.h"
+
 #include "bios_enum_attribute.hpp"
 
 #include "utils.hpp"
@@ -199,6 +201,25 @@
                                                attrType, currValueIndices);
 }
 
+int BIOSEnumAttribute::updateAttrVal(Table& newValue, uint16_t attrHdl,
+                                     uint8_t attrType,
+                                     const PropertyValue& newPropVal)
+{
+    auto iter = valMap.find(newPropVal);
+    if (iter == valMap.end())
+    {
+        std::cerr << "Could not find index for new BIOS enum, value="
+                  << std::get<std::string>(newPropVal) << "\n";
+        return PLDM_ERROR;
+    }
+    auto currentValue = iter->second;
+    std::vector<uint8_t> handleIndices{
+        getValueIndex(currentValue, possibleValues)};
+    table::attribute_value::constructEnumEntry(newValue, attrHdl, attrType,
+                                               handleIndices);
+    return PLDM_SUCCESS;
+}
+
 } // namespace bios
 } // namespace responder
-} // namespace pldm
\ No newline at end of file
+} // namespace pldm
diff --git a/libpldmresponder/bios_enum_attribute.hpp b/libpldmresponder/bios_enum_attribute.hpp
index 2d8667a..c86d9d7 100644
--- a/libpldmresponder/bios_enum_attribute.hpp
+++ b/libpldmresponder/bios_enum_attribute.hpp
@@ -51,6 +51,9 @@
     void constructEntry(const BIOSStringTable& stringTable, Table& attrTable,
                         Table& attrValueTable) override;
 
+    int updateAttrVal(Table& newValue, uint16_t attrHdl, uint8_t attrType,
+                      const PropertyValue& newPropVal);
+
   private:
     std::vector<std::string> possibleValues;
     std::string defaultValue;
@@ -90,4 +93,4 @@
 
 } // namespace bios
 } // namespace responder
-} // namespace pldm
\ No newline at end of file
+} // namespace pldm
diff --git a/libpldmresponder/bios_integer_attribute.cpp b/libpldmresponder/bios_integer_attribute.cpp
index 90667a2..1aae60a 100644
--- a/libpldmresponder/bios_integer_attribute.cpp
+++ b/libpldmresponder/bios_integer_attribute.cpp
@@ -115,7 +115,7 @@
                                                   attrType, currentValue);
 }
 
-uint64_t BIOSIntegerAttribute::getAttrValue(PropertyValue propertyValue)
+uint64_t BIOSIntegerAttribute::getAttrValue(const PropertyValue& propertyValue)
 {
     uint64_t value;
     if (dBusMap->propertyType == "uint8_t")
@@ -172,6 +172,16 @@
     }
 }
 
+int BIOSIntegerAttribute::updateAttrVal(Table& newValue, uint16_t attrHdl,
+                                        uint8_t attrType,
+                                        const PropertyValue& newPropVal)
+{
+    auto newVal = getAttrValue(newPropVal);
+    table::attribute_value::constructIntegerEntry(newValue, attrHdl, attrType,
+                                                  newVal);
+    return PLDM_SUCCESS;
+}
+
 } // namespace bios
 } // namespace responder
-} // namespace pldm
\ No newline at end of file
+} // namespace pldm
diff --git a/libpldmresponder/bios_integer_attribute.hpp b/libpldmresponder/bios_integer_attribute.hpp
index 83fa53d..e180066 100644
--- a/libpldmresponder/bios_integer_attribute.hpp
+++ b/libpldmresponder/bios_integer_attribute.hpp
@@ -47,12 +47,15 @@
     void constructEntry(const BIOSStringTable& stringTable, Table& attrTable,
                         Table& attrValueTable) override;
 
+    int updateAttrVal(Table& newValue, uint16_t attrHdl, uint8_t attrType,
+                      const PropertyValue& newPropVal);
+
   private:
     /** @brief Integer field from json */
     table::attribute::IntegerField integerInfo;
 
     /** @brief Get pldm value from dbus propertyValue */
-    uint64_t getAttrValue(PropertyValue value);
+    uint64_t getAttrValue(const PropertyValue& value);
 
     /** @brief Get value on dbus */
     uint64_t getAttrValue();
@@ -60,4 +63,4 @@
 
 } // namespace bios
 } // namespace responder
-} // namespace pldm
\ No newline at end of file
+} // namespace pldm
diff --git a/libpldmresponder/bios_string_attribute.cpp b/libpldmresponder/bios_string_attribute.cpp
index 1d9ec5d..1b6ba75 100644
--- a/libpldmresponder/bios_string_attribute.cpp
+++ b/libpldmresponder/bios_string_attribute.cpp
@@ -110,6 +110,25 @@
                                                  attrType, currStr);
 }
 
+int BIOSStringAttribute::updateAttrVal(Table& newValue, uint16_t attrHdl,
+                                       uint8_t attrType,
+                                       const PropertyValue& newPropVal)
+{
+    try
+    {
+        const auto& newStringValue = std::get<std::string>(newPropVal);
+        table::attribute_value::constructStringEntry(newValue, attrHdl,
+                                                     attrType, newStringValue);
+    }
+    catch (const std::bad_variant_access& e)
+    {
+        std::cerr << "invalid value passed for the property, error: "
+                  << e.what() << "\n";
+        return PLDM_ERROR;
+    }
+    return PLDM_SUCCESS;
+}
+
 } // namespace bios
 } // namespace responder
 } // namespace pldm
diff --git a/libpldmresponder/bios_string_attribute.hpp b/libpldmresponder/bios_string_attribute.hpp
index 48b0d2d..3b29dc1 100644
--- a/libpldmresponder/bios_string_attribute.hpp
+++ b/libpldmresponder/bios_string_attribute.hpp
@@ -70,6 +70,9 @@
     void constructEntry(const BIOSStringTable& stringTable, Table& attrTable,
                         Table& attrValueTable) override;
 
+    int updateAttrVal(Table& newValue, uint16_t attrHdl, uint8_t attrType,
+                      const PropertyValue& newPropVal);
+
   private:
     /** @brief string field from json */
     table::attribute::StringField stringInfo;