Modify set-value function from external

    Move Special mode from bmcweb to dbus-sensors, this will be handled via dbus-sensor when the user set-value f$
    This is unlikely to break any users because the Intel special mode function is no change, only move to dbus-s$

    The set value function is to filter the external set, excluding the internal set.
    In the external set, if in INSECURE_UNRESTRICTED_SENSOR_OVERRIDE, no need to check before set value else add $

    bmcweb needs to be merged at the same time.
    bmcweb changes are pushed to Gerrit:
    https://gerrit.openbmc-project.xyz/c/openbmc/bmcweb/+/42448

    the mailing list discussion links:
    https://lists.ozlabs.org/pipermail/openbmc/2021-March/025597.html

Signed-off-by: Bruce Lee <Bruce_Lee@quantatw.com>
Change-Id: I0919e4d2343e81045010a2b0d4bf01dc272bcb07
diff --git a/include/Utils.hpp b/include/Utils.hpp
index d2ab5ca..01d941f 100644
--- a/include/Utils.hpp
+++ b/include/Utils.hpp
@@ -316,3 +316,5 @@
     splitFileName(const std::filesystem::path& filePath);
 std::optional<double> readFile(const std::string& thresholdFile,
                                const double& scaleFactor);
+void setupManufacturingModeMatch(sdbusplus::asio::connection& conn);
+bool getManufacturingMode();
diff --git a/include/dbus-sensor_config.h.in b/include/dbus-sensor_config.h.in
new file mode 100644
index 0000000..0e07685
--- /dev/null
+++ b/include/dbus-sensor_config.h.in
@@ -0,0 +1,9 @@
+#pragma once
+
+#include <cstdint>
+
+// clang-format off
+constexpr const bool validateUnsecureFeature = @VALIDATION_UNSECURE_FEATURE@;
+
+constexpr const bool insecureSensorOverride = @INSECURE_UNRESTRICTED_SENSOR_OVERRIDE@;
+// clang-format on
\ No newline at end of file
diff --git a/include/meson.build b/include/meson.build
new file mode 100644
index 0000000..4810de7
--- /dev/null
+++ b/include/meson.build
@@ -0,0 +1,6 @@
+conf_data = configuration_data()
+conf_data.set10('VALIDATION_UNSECURE_FEATURE', get_option('validate-unsecure-feature').enabled())
+conf_data.set10('INSECURE_UNRESTRICTED_SENSOR_OVERRIDE', get_option('insecure-sensor-override').enabled())
+configure_file(input: 'dbus-sensor_config.h.in',
+               output: 'dbus-sensor_config.h',
+               configuration: conf_data)
\ No newline at end of file
diff --git a/include/sensor.hpp b/include/sensor.hpp
index d1fb22e..b98241b 100644
--- a/include/sensor.hpp
+++ b/include/sensor.hpp
@@ -1,4 +1,5 @@
 #pragma once
+#include "dbus-sensor_config.h"
 
 #include <SensorPaths.hpp>
 #include <Thresholds.hpp>
@@ -39,12 +40,13 @@
     Sensor(const std::string& name,
            std::vector<thresholds::Threshold>&& thresholdData,
            const std::string& configurationPath, const std::string& objectType,
-           const double max, const double min,
+           bool isSettable, const double max, const double min,
            std::shared_ptr<sdbusplus::asio::connection>& conn,
            PowerState readState = PowerState::always) :
         name(sensor_paths::escapePathForDbus(name)),
         configurationPath(configurationPath), objectType(objectType),
-        maxValue(max), minValue(min), thresholds(std::move(thresholdData)),
+        isSensorSettable(isSettable), maxValue(max), minValue(min),
+        thresholds(std::move(thresholdData)),
         hysteresisTrigger((max - min) * 0.01),
         hysteresisPublish((max - min) * 0.0001), dbusConnection(conn),
         readState(readState), errCount(0),
@@ -57,6 +59,7 @@
     std::string name;
     std::string configurationPath;
     std::string objectType;
+    bool isSensorSettable;
     double maxValue;
     double minValue;
     std::vector<thresholds::Threshold> thresholds;
@@ -173,6 +176,18 @@
     {
         if (!internalSet)
         {
+            if (insecureSensorOverride == false)
+            { // insecure sesnor override.
+                if (isSensorSettable == false)
+                { // sensor is not settable.
+                    if (getManufacturingMode() == false)
+                    { // manufacture mode is not enable.
+                        throw sdbusplus::exception::SdBusError(
+                            -EACCES, "Not allow set porperty value.");
+                    }
+                }
+            }
+
             oldValue = newValue;
             overriddenState = true;
             // check thresholds for external set
diff --git a/meson.build b/meson.build
index a1e619e..211d855 100644
--- a/meson.build
+++ b/meson.build
@@ -66,7 +66,7 @@
     include_directories: 'include',
 )
 
-
+subdir('include')
 subdir('service_files')
 subdir('src')
 
diff --git a/meson_options.txt b/meson_options.txt
index 918d206..b0214ee 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -10,3 +10,5 @@
 option('psu', type: 'feature', value: 'enabled', description: 'Enable PSU sensor.',)
 option('external', type: 'feature', value: 'enabled', description: 'Enable External sensor.',)
 option('tests', type: 'feature', description: 'Build tests.',)
+option('validate-unsecure-feature', type : 'feature', value : 'disabled', description : 'Enables unsecure features required by validation. Note: mustbe turned off for production images.',)
+option('insecure-sensor-override', type : 'feature', value : 'disabled', description : 'Enables Sensor override feature without any check.',)
diff --git a/src/ADCSensor.cpp b/src/ADCSensor.cpp
index c858df7..ef7a90a 100644
--- a/src/ADCSensor.cpp
+++ b/src/ADCSensor.cpp
@@ -54,7 +54,7 @@
                      std::optional<BridgeGpio>&& bridgeGpio) :
     Sensor(boost::replace_all_copy(sensorName, " ", "_"),
            std::move(thresholdsIn), sensorConfiguration,
-           "xyz.openbmc_project.Configuration.ADC",
+           "xyz.openbmc_project.Configuration.ADC", false,
            maxVoltageReading / scaleFactor, minVoltageReading / scaleFactor,
            conn, readState),
     std::enable_shared_from_this<ADCSensor>(), objServer(objectServer),
diff --git a/src/ADCSensorMain.cpp b/src/ADCSensorMain.cpp
index edc055a..9d29895 100644
--- a/src/ADCSensorMain.cpp
+++ b/src/ADCSensorMain.cpp
@@ -406,5 +406,6 @@
             "',arg0namespace='xyz.openbmc_project.Inventory.Item'",
         cpuPresenceHandler));
 
+    setupManufacturingModeMatch(*systemBus);
     io.run();
 }
diff --git a/src/CPUSensor.cpp b/src/CPUSensor.cpp
index 40b86d1..f12a0b7 100644
--- a/src/CPUSensor.cpp
+++ b/src/CPUSensor.cpp
@@ -41,8 +41,8 @@
                      const std::string& sensorConfiguration, int cpuId,
                      bool show, double dtsOffset) :
     Sensor(boost::replace_all_copy(sensorName, " ", "_"),
-           std::move(thresholdsIn), sensorConfiguration, objectType, 0, 0, conn,
-           PowerState::on),
+           std::move(thresholdsIn), sensorConfiguration, objectType, false, 0,
+           0, conn, PowerState::on),
     objServer(objectServer), inputDev(io), waitTimer(io), path(path),
     privTcontrol(std::numeric_limits<double>::quiet_NaN()),
     dtsOffset(dtsOffset), show(show), pollTime(CPUSensor::sensorPollMs),
diff --git a/src/CPUSensorMain.cpp b/src/CPUSensorMain.cpp
index b36e6ad..eb619b9 100644
--- a/src/CPUSensorMain.cpp
+++ b/src/CPUSensorMain.cpp
@@ -772,5 +772,7 @@
     }
 
     systemBus->request_name("xyz.openbmc_project.CPUSensor");
+
+    setupManufacturingModeMatch(*systemBus);
     io.run();
 }
diff --git a/src/ExitAirTempSensor.cpp b/src/ExitAirTempSensor.cpp
index ed24155..1cd55b8 100644
--- a/src/ExitAirTempSensor.cpp
+++ b/src/ExitAirTempSensor.cpp
@@ -164,8 +164,8 @@
                      std::shared_ptr<ExitAirTempSensor>& parent) :
     Sensor(boost::replace_all_copy(sensorName, " ", "_"),
            std::move(thresholdData), sensorConfiguration,
-           "xyz.openbmc_project.Configuration.ExitAirTemp", cfmMaxReading,
-           cfmMinReading, conn, PowerState::on),
+           "xyz.openbmc_project.Configuration.ExitAirTemp", false,
+           cfmMaxReading, cfmMinReading, conn, PowerState::on),
     std::enable_shared_from_this<CFMSensor>(), parent(parent),
     objServer(objectServer)
 {
@@ -513,8 +513,8 @@
     std::vector<thresholds::Threshold>&& thresholdData) :
     Sensor(boost::replace_all_copy(sensorName, " ", "_"),
            std::move(thresholdData), sensorConfiguration,
-           "xyz.openbmc_project.Configuration.ExitAirTemp", exitAirMaxReading,
-           exitAirMinReading, conn, PowerState::on),
+           "xyz.openbmc_project.Configuration.ExitAirTemp", false,
+           exitAirMaxReading, exitAirMinReading, conn, PowerState::on),
     std::enable_shared_from_this<ExitAirTempSensor>(), objServer(objectServer)
 {
     sensorInterface = objectServer.add_interface(
diff --git a/src/ExternalSensor.cpp b/src/ExternalSensor.cpp
index 22f5058..17f5300 100644
--- a/src/ExternalSensor.cpp
+++ b/src/ExternalSensor.cpp
@@ -32,8 +32,8 @@
     // because that is the entire point of ExternalSensor,
     // to accept sensor values written by an external source.
     Sensor(boost::replace_all_copy(sensorName, " ", "_"),
-           std::move(thresholdsIn), sensorConfiguration, objectType, maxReading,
-           minReading, conn, powerState),
+           std::move(thresholdsIn), sensorConfiguration, objectType, true,
+           maxReading, minReading, conn, powerState),
     std::enable_shared_from_this<ExternalSensor>(), objServer(objectServer),
     writeLast(std::chrono::steady_clock::now()),
     writeTimeout(
diff --git a/src/FanMain.cpp b/src/FanMain.cpp
index e613494..30f0ca4 100644
--- a/src/FanMain.cpp
+++ b/src/FanMain.cpp
@@ -525,5 +525,6 @@
         std::move(redundancyHandler));
     matches.emplace_back(std::move(match));
 
+    setupManufacturingModeMatch(*systemBus);
     io.run();
 }
diff --git a/src/HwmonTempMain.cpp b/src/HwmonTempMain.cpp
index 60a8fde..2d39f97 100644
--- a/src/HwmonTempMain.cpp
+++ b/src/HwmonTempMain.cpp
@@ -353,5 +353,6 @@
         matches.emplace_back(std::move(match));
     }
 
+    setupManufacturingModeMatch(*systemBus);
     io.run();
 }
diff --git a/src/HwmonTempSensor.cpp b/src/HwmonTempSensor.cpp
index 72b20d0..bd89c4c 100644
--- a/src/HwmonTempSensor.cpp
+++ b/src/HwmonTempSensor.cpp
@@ -45,8 +45,8 @@
     std::vector<thresholds::Threshold>&& thresholdsIn, const float pollRate,
     const std::string& sensorConfiguration, const PowerState powerState) :
     Sensor(boost::replace_all_copy(sensorName, " ", "_"),
-           std::move(thresholdsIn), sensorConfiguration, objectType, maxReading,
-           minReading, conn, powerState),
+           std::move(thresholdsIn), sensorConfiguration, objectType, false,
+           maxReading, minReading, conn, powerState),
     std::enable_shared_from_this<HwmonTempSensor>(), objServer(objectServer),
     inputDev(io, open(path.c_str(), O_RDONLY)), waitTimer(io), path(path),
     sensorPollMs(static_cast<unsigned int>(pollRate * 1000))
diff --git a/src/IpmbSensor.cpp b/src/IpmbSensor.cpp
index 503a256..22e4862 100644
--- a/src/IpmbSensor.cpp
+++ b/src/IpmbSensor.cpp
@@ -66,8 +66,8 @@
                        std::string& sensorTypeName) :
     Sensor(boost::replace_all_copy(sensorName, " ", "_"),
            std::move(thresholdData), sensorConfiguration,
-           "xyz.openbmc_project.Configuration.ExitAirTemp", ipmbMaxReading,
-           ipmbMinReading, conn, PowerState::on),
+           "xyz.openbmc_project.Configuration.ExitAirTemp", false,
+           ipmbMaxReading, ipmbMinReading, conn, PowerState::on),
     deviceAddress(deviceAddress), hostSMbusIndex(hostSMbusIndex),
     objectServer(objectServer), waitTimer(io)
 {
@@ -644,5 +644,6 @@
             std::string(power::interface) + "'",
         reinitSensors);
 
+    setupManufacturingModeMatch(*systemBus);
     io.run();
 }
diff --git a/src/MCUTempSensor.cpp b/src/MCUTempSensor.cpp
index 6a64c16..2f5e64c 100644
--- a/src/MCUTempSensor.cpp
+++ b/src/MCUTempSensor.cpp
@@ -58,8 +58,8 @@
                              uint8_t tempReg) :
     Sensor(boost::replace_all_copy(sensorName, " ", "_"),
            std::move(thresholdData), sensorConfiguration,
-           "xyz.openbmc_project.Configuration.ExitAirTemp", mcuTempMaxReading,
-           mcuTempMinReading, conn),
+           "xyz.openbmc_project.Configuration.ExitAirTemp", false,
+           mcuTempMaxReading, mcuTempMinReading, conn),
     busId(busId), mcuAddress(mcuAddress), tempReg(tempReg),
     objectServer(objectServer), waitTimer(io)
 {
@@ -310,5 +310,6 @@
             configInterface + "'",
         eventHandler);
 
+    setupManufacturingModeMatch(*systemBus);
     io.run();
 }
diff --git a/src/NVMeSensor.cpp b/src/NVMeSensor.cpp
index cd0c919..3c7edca 100644
--- a/src/NVMeSensor.cpp
+++ b/src/NVMeSensor.cpp
@@ -31,9 +31,9 @@
                        const int busNumber) :
     Sensor(boost::replace_all_copy(sensorName, " ", "_"),
            std::move(thresholdsIn), sensorConfiguration,
-           "xyz.openbmc_project.Configuration.NVMe", maxReading, minReading,
-           conn, PowerState::on),
-    bus(busNumber), objServer(objectServer)
+           "xyz.openbmc_project.Configuration.NVMe", false, maxReading,
+           minReading, conn, PowerState::on),
+    objServer(objectServer), bus(busNumber)
 {
     sensorInterface = objectServer.add_interface(
         "/xyz/openbmc_project/sensors/temperature/" + name,
diff --git a/src/NVMeSensorMain.cpp b/src/NVMeSensorMain.cpp
index 49475fc..fc9eb2f 100644
--- a/src/NVMeSensorMain.cpp
+++ b/src/NVMeSensorMain.cpp
@@ -187,5 +187,6 @@
             std::string(sensorType) + "'",
         eventHandler);
 
+    setupManufacturingModeMatch(*systemBus);
     io.run();
 }
diff --git a/src/PSUSensor.cpp b/src/PSUSensor.cpp
index a528819..942cfc3 100644
--- a/src/PSUSensor.cpp
+++ b/src/PSUSensor.cpp
@@ -45,8 +45,8 @@
                      double max, double min, const std::string& label,
                      size_t tSize) :
     Sensor(boost::replace_all_copy(sensorName, " ", "_"),
-           std::move(thresholdsIn), sensorConfiguration, objectType, max, min,
-           conn),
+           std::move(thresholdsIn), sensorConfiguration, objectType, false, max,
+           min, conn),
     std::enable_shared_from_this<PSUSensor>(), objServer(objectServer),
     inputDev(io), waitTimer(io), path(path), pathRatedMax(""), pathRatedMin(""),
     sensorFactor(factor), minMaxReadCounter(0)
diff --git a/src/PSUSensorMain.cpp b/src/PSUSensorMain.cpp
index 6595db9..3f0dfbf 100644
--- a/src/PSUSensorMain.cpp
+++ b/src/PSUSensorMain.cpp
@@ -1000,5 +1000,7 @@
             eventHandler);
         matches.emplace_back(std::move(match));
     }
+
+    setupManufacturingModeMatch(*systemBus);
     io.run();
 }
diff --git a/src/TachSensor.cpp b/src/TachSensor.cpp
index b3c955c..7242c96 100644
--- a/src/TachSensor.cpp
+++ b/src/TachSensor.cpp
@@ -52,8 +52,8 @@
                        const PowerState& powerState,
                        const std::optional<std::string>& ledIn) :
     Sensor(boost::replace_all_copy(fanName, " ", "_"), std::move(thresholdsIn),
-           sensorConfiguration, objectType, limits.second, limits.first, conn,
-           powerState),
+           sensorConfiguration, objectType, false, limits.second, limits.first,
+           conn, powerState),
     objServer(objectServer), redundancy(redundancy),
     presence(std::move(presenceSensor)),
     inputDev(io, open(path.c_str(), O_RDONLY)), waitTimer(io), path(path),
diff --git a/src/Utils.cpp b/src/Utils.cpp
index 5217129..cf0ce9a 100644
--- a/src/Utils.cpp
+++ b/src/Utils.cpp
@@ -14,6 +14,8 @@
 // limitations under the License.
 */
 
+#include "dbus-sensor_config.h"
+
 #include <Utils.hpp>
 #include <boost/algorithm/string/predicate.hpp>
 #include <boost/container/flat_map.hpp>
@@ -35,6 +37,7 @@
 
 static bool powerStatusOn = false;
 static bool biosHasPost = false;
+static bool manufacturingMode = false;
 
 static std::unique_ptr<sdbusplus::bus::match::match> powerMatch = nullptr;
 static std::unique_ptr<sdbusplus::bus::match::match> postMatch = nullptr;
@@ -504,3 +507,54 @@
     }
     return std::nullopt;
 }
+
+void setupManufacturingModeMatch(sdbusplus::asio::connection& conn)
+{
+    static std::unique_ptr<sdbusplus::bus::match::match>
+        setupManufacturingModeMatch =
+            std::make_unique<sdbusplus::bus::match::match>(
+                conn,
+                "type='signal',interface='org.freedesktop.DBus."
+                "Properties',member='"
+                "PropertiesChanged',arg0namespace='xyz.openbmc_project."
+                "Security.SpecialMode'",
+                [](sdbusplus::message::message& msg) {
+                    std::string interfaceName;
+                    boost::container::flat_map<std::string,
+                                               std::variant<std::string>>
+                        propertiesChanged;
+                    std::string manufacturingModeStatus;
+
+                    msg.read(interfaceName, propertiesChanged);
+                    if (propertiesChanged.begin() == propertiesChanged.end())
+                    {
+                        return;
+                    }
+
+                    manufacturingModeStatus = std::get<std::string>(
+                        propertiesChanged.begin()->second);
+                    manufacturingMode = false;
+                    if (manufacturingModeStatus ==
+                        "xyz.openbmc_project.Control.Security."
+                        "SpecialMode.Modes.Manufacturing")
+                    {
+                        manufacturingMode = true;
+                    }
+                    if (validateUnsecureFeature == true)
+                    {
+                        if (manufacturingModeStatus ==
+                            "xyz.openbmc_project.Control.Security."
+                            "SpecialMode.Modes.ValidationUnsecure")
+                        {
+                            manufacturingMode = true;
+                        }
+                    }
+                });
+
+    return;
+}
+
+bool getManufacturingMode()
+{
+    return manufacturingMode;
+}
\ No newline at end of file