Move commands from ipmi-providers

Many commands were in ipmi-providers and need to be moved into the
active development library (intel-ipmi-oem). This copies wholesale
those commands, even though many need to be rewritten to use the new
ipmi providers API.

Tested-by: build and see that the commands are still present even when
           the ipmi-providers library is removed

Change-Id: If326f5d7844adeed7da2d3b7a2f1d3eeeea43b29
Signed-off-by: Vernon Mauery <vernon.mauery@linux.intel.com>
diff --git a/CMakeLists.txt b/CMakeLists.txt
index c7b0a80..70514df 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -19,8 +19,12 @@
 add_definitions (-DBOOST_NO_TYPEID)
 add_definitions (-DBOOST_ASIO_DISABLE_THREADS)
 add_definitions (-DBOOST_COROUTINES_NO_DEPRECATION_WARNING)
+add_definitions (-Wno-psabi)
 
 if (NOT YOCTO)
+    # headers that can't be built without yocto
+    include_directories (non-yocto)
+
     configure_file (CMakeLists.txt.in 3rdparty/CMakeLists.txt)
     execute_process (
         COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" .
@@ -79,9 +83,17 @@
 
 include_directories (${CMAKE_CURRENT_SOURCE_DIR}/include)
 
+#
+# import OpenSSL (crypto)
+find_package (OpenSSL REQUIRED)
+include_directories (${OPENSSL_INCLUDE_DIR})
+
 add_library (
     zinteloemcmds SHARED src/oemcommands.cpp src/sensorcommands.cpp
     src/storagecommands.cpp src/multinodecommands.cpp src/firmware-update.cpp
+    src/smbioshandler.cpp src/smbiosmdrv2handler.cpp
+    src/manufacturingcommands.cpp src/bmccontrolservices.cpp
+    src/bridgingcommands.cpp
 )
 set_target_properties (zinteloemcmds PROPERTIES VERSION "0.1.0")
 set_target_properties (zinteloemcmds PROPERTIES SOVERSION "0")
@@ -91,5 +103,6 @@
 target_link_libraries (zinteloemcmds intel_dbus)
 target_link_libraries (zinteloemcmds -luserlayer)
 target_link_libraries (zinteloemcmds -lchannellayer)
+target_link_libraries (zinteloemcmds ${OPENSSL_CRYPTO_LIBRARY})
 
 install (TARGETS zinteloemcmds DESTINATION lib/ipmid-providers)
diff --git a/include/bridgingcommands.hpp b/include/bridgingcommands.hpp
new file mode 100644
index 0000000..e277b58
--- /dev/null
+++ b/include/bridgingcommands.hpp
@@ -0,0 +1,347 @@
+/*
+// Copyright (c) 2018 Intel Corporation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+#pragma once
+#include <sdbusplus/message.hpp>
+#include <sdbusplus/server/interface.hpp>
+
+/**
+ * @brief Response queue defines
+ */
+constexpr int responseQueueMaxSize = 20;
+
+/**
+ * @brief Ipmb misc
+ */
+constexpr uint8_t ipmbLunMask = 0x03;
+constexpr uint8_t ipmbSeqMask = 0x3F;
+constexpr uint8_t ipmbMeSlaveAddress = 0x2C;
+constexpr uint8_t ipmbMeChannelNum = 1;
+
+/**
+ * @brief Ipmb getters
+ */
+constexpr uint8_t ipmbNetFnGet(uint8_t netFnLun)
+{
+    return netFnLun >> 2;
+}
+
+constexpr uint8_t ipmbLunFromNetFnLunGet(uint8_t netFnLun)
+{
+    return netFnLun & ipmbLunMask;
+}
+
+constexpr uint8_t ipmbSeqGet(uint8_t seqNumLun)
+{
+    return seqNumLun >> 2;
+}
+
+constexpr uint8_t ipmbLunFromSeqLunGet(uint8_t seqNumLun)
+{
+    return seqNumLun & ipmbLunMask;
+}
+
+/**
+ * @brief Ipmb setters
+ */
+constexpr uint8_t ipmbNetFnLunSet(uint8_t netFn, uint8_t lun)
+{
+    return ((netFn << 2) | (lun & ipmbLunMask));
+}
+
+constexpr uint8_t ipmbSeqLunSet(uint8_t seq, uint8_t lun)
+{
+    return ((seq << 2) | (lun & ipmbLunMask));
+}
+
+constexpr size_t ipmbMaxDataSize = 256;
+constexpr size_t ipmbConnectionHeaderLength = 3;
+constexpr size_t ipmbResponseDataHeaderLength = 4;
+constexpr size_t ipmbRequestDataHeaderLength = 3;
+constexpr size_t ipmbChecksum2StartOffset = 3;
+constexpr size_t ipmbChecksumSize = 1;
+constexpr size_t ipmbMinFrameLength = 7;
+constexpr size_t ipmbMaxFrameLength = ipmbConnectionHeaderLength +
+                                      ipmbResponseDataHeaderLength +
+                                      ipmbChecksumSize + ipmbMaxDataSize;
+
+/**
+ * @brief Channel types
+ */
+constexpr uint8_t targetChannelIpmb = 0x1;
+constexpr uint8_t targetChannelIcmb10 = 0x2;
+constexpr uint8_t targetChannelIcmb09 = 0x3;
+constexpr uint8_t targetChannelLan = 0x4;
+constexpr uint8_t targetChannelSerialModem = 0x5;
+constexpr uint8_t targetChannelOtherLan = 0x6;
+constexpr uint8_t targetChannelPciSmbus = 0x7;
+constexpr uint8_t targetChannelSmbus10 = 0x8;
+constexpr uint8_t targetChannelSmbus20 = 0x9;
+constexpr uint8_t targetChannelSystemInterface = 0xC;
+
+/**
+ * @brief Channel modes
+ */
+constexpr uint8_t modeNoTracking = 0x0;
+constexpr uint8_t modeTrackRequest = 0x1;
+constexpr uint8_t modeSendRaw = 0x2;
+
+/**
+ * @brief Command specific codes
+ */
+constexpr ipmi_return_codes ipmiGetMessageCmdDataNotAvailable =
+    static_cast<ipmi_return_codes>(0x80);
+
+/**
+ * @brief Ipmb frame
+ */
+typedef struct
+{
+    /// @brief IPMB frame header
+    union
+    {
+        /// @brief IPMB request header
+        struct
+        {
+            /** @brief IPMB Connection Header Format */
+            uint8_t address;
+            uint8_t rsNetFnLUN;
+            uint8_t checksum1;
+            /** @brief IPMB Header */
+            uint8_t rqSA;
+            uint8_t rqSeqLUN;
+            uint8_t cmd;
+            uint8_t data[];
+        } Req;
+        /// @brief IPMB response header
+        struct
+        {
+            uint8_t address;
+            /** @brief IPMB Connection Header Format */
+            uint8_t rqNetFnLUN;
+            uint8_t checksum1;
+            /** @brief IPMB Header */
+            uint8_t rsSA;
+            uint8_t rsSeqLUN;
+            uint8_t cmd;
+            uint8_t completionCode;
+            uint8_t data[];
+        } Resp;
+    } Header;
+} __attribute__((packed)) ipmbHeader;
+
+/**
+ * @brief Ipmb messages
+ */
+struct IpmbRequest
+{
+    uint8_t address;
+    uint8_t netFn;
+    uint8_t rsLun;
+    uint8_t rqSA;
+    uint8_t seq;
+    uint8_t rqLun;
+    uint8_t cmd;
+    std::vector<uint8_t> data;
+
+    IpmbRequest(const ipmbHeader *ipmbBuffer, size_t bufferLength);
+
+    void prepareRequest(sdbusplus::message::message &mesg);
+};
+
+struct IpmbResponse
+{
+    uint8_t address;
+    uint8_t netFn;
+    uint8_t rqLun;
+    uint8_t rsSA;
+    uint8_t seq;
+    uint8_t rsLun;
+    uint8_t cmd;
+    uint8_t completionCode;
+    std::vector<uint8_t> data;
+
+    IpmbResponse(uint8_t address, uint8_t netFn, uint8_t rqLun, uint8_t rsSA,
+                 uint8_t seq, uint8_t rsLun, uint8_t cmd,
+                 uint8_t completionCode, std::vector<uint8_t> &inputData);
+
+    void ipmbToi2cConstruct(uint8_t *buffer, size_t *bufferLength);
+};
+
+/**
+ * @brief Send Message Request
+ */
+typedef struct
+{
+    uint8_t channelData;
+    uint8_t data[];
+
+    constexpr uint8_t channelNumGet()
+    {
+        return (channelData & 0xF);
+    }
+
+    constexpr uint8_t authenticationGet()
+    {
+        return ((channelData & 0x10) >> 4);
+    }
+
+    constexpr uint8_t encryptionGet()
+    {
+        return ((channelData & 0x20) >> 5);
+    }
+
+    constexpr uint8_t modeGet()
+    {
+        return ((channelData & 0xC0) >> 6);
+    }
+} __attribute__((packed)) sSendMessageReq;
+
+/**
+ * @brief Get Message Response
+ */
+typedef struct
+{
+    uint8_t channelData;
+    uint8_t data[];
+
+    constexpr void channelNumSet(uint8_t num)
+    {
+        channelData |= num & 0xF;
+    }
+
+    constexpr void privilegeLvlSet(CommandPrivilege privLvl)
+    {
+        channelData |= static_cast<uint8_t>(privLvl) & 0xF0;
+    }
+} __attribute__((packed)) sGetMessageRes;
+
+/**
+ * @brief Get Message Flags Response
+ */
+typedef struct
+{
+    uint8_t flags;
+
+    constexpr void receiveMessageBitSet(uint8_t value)
+    {
+        flags |= (value & 1);
+    }
+
+    constexpr void eventMessageBitSet(uint8_t value)
+    {
+        flags |= (value & 1) << 1;
+    }
+
+    constexpr void watchdogTimeoutBitSet(uint8_t value)
+    {
+        flags |= (value & 1) << 3;
+    }
+
+    constexpr void oem0BitSet(uint8_t value)
+    {
+        flags |= (value & 1) << 5;
+    }
+
+    constexpr void oem1BitSet(uint8_t value)
+    {
+        flags |= (value & 1) << 6;
+    }
+
+    constexpr void oem2BitSet(uint8_t value)
+    {
+        flags |= (value & 1) << 7;
+    }
+} __attribute__((packed)) sGetMessageFlagsResp;
+
+/**
+ * @brief Clear Message Flags Request
+ */
+typedef struct
+{
+    uint8_t flags;
+
+    constexpr uint8_t receiveMessageBitGet()
+    {
+        return (flags & 0x1);
+    }
+
+    constexpr uint8_t eventMessageBitGet()
+    {
+        return ((flags & 0x2) >> 1);
+    }
+
+    constexpr uint8_t watchdogTimeoutBitGet()
+    {
+        return ((flags & 0x8) >> 3);
+    }
+
+    constexpr uint8_t oem0BitGet()
+    {
+        return ((flags & 0x20) >> 5);
+    }
+
+    constexpr uint8_t oem1BitGet()
+    {
+        return ((flags & 0x40) >> 6);
+    }
+
+    constexpr uint8_t oem2BitGet()
+    {
+        return ((flags & 0x80) >> 7);
+    }
+} __attribute__((packed)) sClearMessageFlagsReq;
+
+/** @class Bridging
+ *
+ *  @brief Implement commands to support IPMI bridging.
+ */
+class Bridging
+{
+  public:
+    Bridging();
+
+    ipmi_return_codes sendMessageHandler(ipmi_request_t request,
+                                         ipmi_response_t response,
+                                         ipmi_data_len_t dataLen);
+
+    ipmi_return_codes getMessageHandler(ipmi_request_t request,
+                                        ipmi_response_t response,
+                                        ipmi_data_len_t dataLen);
+
+    ipmi_return_codes clearMessageFlagsHandler(ipmi_request_t request,
+                                               ipmi_response_t response,
+                                               ipmi_data_len_t dataLen);
+
+    ipmi_return_codes getMessageFlagsHandler(ipmi_request_t request,
+                                             ipmi_response_t response,
+                                             ipmi_data_len_t dataLen);
+
+    enum IpmiAppBridgingCmds
+    {
+        ipmiCmdClearMessageFlags = 0x30,
+        ipmiCmdGetMessageFlags = 0x31,
+        ipmiCmdGetMessage = 0x33,
+        ipmiCmdSendMessage = 0x34,
+    };
+
+  private:
+    std::vector<IpmbResponse> responseQueue;
+    sdbusplus::bus::bus dbus;
+
+    ipmi_return_codes handleIpmbChannel(sSendMessageReq *sendMsgReq,
+                                        ipmi_response_t response,
+                                        ipmi_data_len_t dataLen);
+};
diff --git a/include/manufacturingcommands.hpp b/include/manufacturingcommands.hpp
new file mode 100644
index 0000000..bc70d84
--- /dev/null
+++ b/include/manufacturingcommands.hpp
@@ -0,0 +1,291 @@
+/*
+// Copyright (c) 2018 Intel Corporation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+
+#pragma once
+
+#include <ipmid/api-types.hpp>
+#include <ipmid/utils.hpp>
+#include <phosphor-logging/log.hpp>
+#include <sdbusplus/bus.hpp>
+#include <sdbusplus/message.hpp>
+#include <sdbusplus/timer.hpp>
+#include <variantvisitors.hpp>
+#include <vector>
+
+#define FAN_SENSOR_NOT_PRESENT (0 << 0)
+#define FAN_SENSOR_PRESENT (1 << 0)
+#define FAN_NOT_PRESENT (0 << 1)
+#define FAN_PRESENT (1 << 1)
+
+namespace ipmi
+{
+
+// TODO: Service names may change. Worth to consider dynamic detection.
+static constexpr const char* fanService = "xyz.openbmc_project.FanSensor";
+static constexpr const char* gpioService = "xyz.openbmc_project.Gpio";
+static constexpr const char* ledServicePrefix =
+    "xyz.openbmc_project.LED.Controller.";
+
+static constexpr const char* ledPathPrefix =
+    "/xyz/openbmc_project/led/physical/";
+static constexpr const char* fanPwmPath =
+    "/xyz/openbmc_project/sensors/fan_pwm/Pwm_";
+static constexpr const char* fanTachPathPrefix =
+    "/xyz/openbmc_project/sensors/fan_tach/Fan_";
+
+static constexpr const char* fanIntf = "xyz.openbmc_project.Sensor.Value";
+static constexpr const char* gpioIntf = "xyz.openbmc_project.Control.Gpio";
+static constexpr const char* ledIntf = "xyz.openbmc_project.Led.Physical";
+
+static constexpr const char* busPropertyIntf =
+    "org.freedesktop.DBus.Properties";
+static constexpr const char* ledStateStr =
+    "xyz.openbmc_project.Led.Physical.Action."; // Comes with postfix Off/On
+static constexpr const char* smGetSignalPathPrefix =
+    "/xyz/openbmc_project/control/gpio/";
+
+/** @enum MtmLvl
+.*
+ *  Manufacturing command access levels
+ */
+enum class MtmLvl
+{
+    mtmNotRunning = 0x00,
+    mtmExpired = 0x01,
+    mtmAvailable = 0x02,
+};
+
+enum class SmActionGet : uint8_t
+{
+    sample = 0,
+    ignore = 1,
+    revert = 2
+};
+
+enum class SmActionSet : uint8_t
+{
+    forceDeasserted = 0,
+    forceAsserted = 1,
+    revert = 2
+};
+
+enum class SmSignalGet : uint8_t
+{
+    smPowerButton = 0,
+    smResetButton = 1,
+    smSleepButton,
+    smNmiButton = 3,
+    smChassisIntrusion = 4,
+    smPowerGood,
+    smPowerRequestGet,
+    smSleepRequestGet,
+    smFrbTimerHaltGet,
+    smForceUpdate,
+    smRingIndication,
+    smCarrierDetect,
+    smIdentifyButton = 0xc,
+    smFanPwmGet = 0xd,
+    smSignalReserved,
+    smFanTachometerGet = 0xf,
+    smNcsiDiag = 0x10,
+    smFpLcpLeftButton = 0x11,
+    smFpLcpRightButton,
+    smFpLcpEnterButton,
+    smGetSignalMax
+};
+
+enum class SmSignalSet : uint8_t
+{
+    smPowerLed = 0,
+    smPowerFaultLed,
+    smClusterLed,
+    smDiskFaultLed,
+    smCoolingFaultLed,
+    smFanPowerSpeed = 5,
+    smPowerRequestSet,
+    smSleepRequestSet,
+    smAcpiSci,
+    smSpeaker,
+    smFanPackFaultLed,
+    smCpuFailLed,
+    smDimmFailLed,
+    smIdentifyLed,
+    smHddLed,
+    smSystemReadyLed,
+    smLcdBacklight = 0x10,
+    smSetSignalMax
+};
+
+struct SetSmSignalReq
+{
+    SmSignalSet Signal;
+    uint8_t Instance;
+    SmActionSet Action;
+    uint8_t Value;
+};
+
+struct GetSmSignalReq
+{
+    SmSignalGet Signal;
+    uint8_t Instance;
+    SmActionGet Action;
+};
+
+struct GetSmSignalRsp
+{
+    uint8_t SigVal;
+    uint8_t SigVal1;
+    uint8_t SigVal2;
+};
+
+class LedProperty
+{
+    SmSignalSet signal;
+    std::string name;
+    std::string prevState;
+    std::string currentState;
+    bool isLocked;
+
+  public:
+    LedProperty(SmSignalSet signal_, std::string name_) :
+        signal(signal_), name(name_), prevState(""), isLocked(false)
+    {
+    }
+
+    LedProperty() = delete;
+
+    SmSignalSet getSignal() const
+    {
+        return signal;
+    }
+
+    void setLock(const bool& lock)
+    {
+        isLocked = lock;
+    }
+    void setPrevState(const std::string& state)
+    {
+        prevState = state;
+    }
+    void setCurrState(const std::string& state)
+    {
+        currentState = state;
+    }
+    std::string getCurrState() const
+    {
+        return currentState;
+    }
+    bool getLock() const
+    {
+        return isLocked;
+    }
+    std::string getPrevState() const
+    {
+        return prevState;
+    }
+    std::string getName() const
+    {
+        return name;
+    }
+};
+
+/** @class Manufacturing
+ *
+ *  @brief Implemet commands to support Manufacturing Test Mode.
+ */
+class Manufacturing
+{
+    std::string path;
+    std::string gpioPaths[(uint8_t)SmSignalGet::smGetSignalMax];
+    std::vector<LedProperty> ledPropertyList;
+    void initData();
+
+  public:
+    Manufacturing();
+
+    ipmi_return_codes detectAccessLvl(ipmi_request_t request,
+                                      ipmi_data_len_t req_len);
+
+    LedProperty* findLedProperty(const SmSignalSet& signal)
+    {
+        auto it = std::find_if(ledPropertyList.begin(), ledPropertyList.end(),
+                               [&signal](const LedProperty& led) {
+                                   return led.getSignal() == signal;
+                               });
+        if (it != ledPropertyList.end())
+        {
+            return &(*it);
+        }
+        return nullptr;
+    }
+
+    std::string getLedPropertyName(const SmSignalSet signal)
+    {
+        LedProperty* led = findLedProperty(signal);
+        if (led != nullptr)
+        {
+            return led->getName();
+        }
+        else
+        {
+            return "";
+        }
+    }
+
+    int8_t getProperty(const char* service, std::string path,
+                       const char* interface, std::string propertyName,
+                       ipmi::Value* value);
+    int8_t setProperty(const char* service, std::string path,
+                       const char* interface, std::string propertyName,
+                       ipmi::Value value);
+    int8_t disablePidControlService(const bool disable);
+
+    void revertTimerHandler();
+
+    std::tuple<uint8_t, ipmi_ret_t, uint8_t> proccessSignal(SmSignalGet signal,
+                                                            SmActionGet action);
+
+    std::string getGpioPathForSmSignal(uint8_t gpioInstane)
+    {
+        return smGetSignalPathPrefix + gpioPaths[gpioInstane];
+    }
+
+    MtmLvl getAccessLvl(void)
+    {
+        static MtmLvl mtmMode = MtmLvl::mtmNotRunning;
+        if (mtmMode != MtmLvl::mtmExpired)
+        {
+            ipmi::Value mode;
+            if (getProperty("xyz.openbmc_project.SpeciaMode",
+                            "/xyz/openbmc_project/security/specialMode",
+                            "xyz.openbmc_project.Security.SpecialMode",
+                            "SpecialMode", &mode) != 0)
+            {
+                mtmMode = MtmLvl::mtmExpired;
+                return mtmMode;
+            }
+            mtmMode = static_cast<MtmLvl>(std::get<std::uint8_t>(mode));
+        }
+        return mtmMode;
+    }
+
+    std::vector<SmSignalGet> revertSmSignalGetVector;
+    bool revertFanPWM = false;
+    bool revertLedCallback = false;
+    phosphor::Timer revertTimer;
+};
+
+} // namespace ipmi
diff --git a/include/oemcommands.hpp b/include/oemcommands.hpp
index 2d2042d..e0e6903 100644
--- a/include/oemcommands.hpp
+++ b/include/oemcommands.hpp
@@ -366,3 +366,73 @@
     maxPwm = 0x3,
     cfm = 0x4
 };
+
+// FIXME: this stuff needs to be rewritten
+enum IPMI_INTEL_OEM_RETURN_CODES
+{
+    IPMI_CC_OEM_PAYLOAD_ACTIVE = 0x80,
+    IPMI_CC_OEM_INVALID_PCIE_SLOTID = 0x80,
+    IPMI_CC_OEM_PARAMETER_NOT_SUPPORTED = 0x80,
+    IPMI_CC_OEM_PAYLOAD_ALREADY_DEACTIVATED = 0x80,
+    IPMI_CC_OEM_SET_IN_PROCESS = 0x81,
+    IPMI_CC_OEM_PAYLOAD_DISABLE = 0x81,
+    IPMI_CC_OEM_LOST_ARBITRATION = 0x81,
+    IPMI_CC_OEM_INVALID_CABLE_PORT_INDEX = 0x81,
+    IPMI_CC_OEM_HEALTH_STATUS_NOT_AVAILABLE = 0x81,
+    IPMI_CC_OEM_BUS_ERROR = 0x82,
+    IPMI_CC_OEM_READ_ONLY = 0x82,
+    IPMI_CC_OEM_WRITE_ONLY = 0x82,
+    IPMI_CC_OEM_NO_CABLE_PRESENT = 0x82,
+    IPMI_CC_OEM_DATA_COLLECTION_IN_PROGRESS = 0x82,
+    IPMI_CC_OEM_PAYLOAD_ACTIVATION_LIMIT_REACH = 0x82,
+    IPMI_CC_OEM_NACK_ON_WRITE = 0x83,
+    IPMI_CC_OEM_DATA_COLLECTION_FAILED = 0x83,
+    IPMI_CC_OEM_CAN_NOT_ACTIVATE_WITH_ENCRYPTION = 0x83,
+    IPMI_CC_OEM_CAN_NOT_ACTIVATE_WITHOUT_ENCRYPTION = 0x84,
+    IPMI_CC_OEM_INVALID_CHECKSUM = 0x85,
+    IPMI_CC_OEM_NO_CABLED_PCIE_PORTS_AVAILABLE = 0xC2,
+};
+
+enum IPMI_RETURN_CODE_EXT
+{
+    IPMI_CC_INVALID_LUN = 0xC2,
+    IPMI_CC_STORGE_LEAK = 0xC4,
+    IPMI_CC_REQUEST_DATA_TRUNCATED = 0xC6,
+    IPMI_CC_REQUEST_DATA_FIELD_LENGTH_LIMIT_EXCEEDED = 0xC8,
+    IPMI_CC_CANNOT_RETURN_NUMBER_OF_REQUESTED_DATA_BYTES = 0xCA,
+    IPMI_CC_REQUEST_SENSOR_DATA_RECORD_NOT_FOUND = 0xCB,
+    IPMI_CC_DESTINATION_UNAVAILABLE = 0xD3,
+    IPMI_CC_PARAMETER_NOT_SUPPORT_IN_PRESENT_STATE = 0xD5,
+};
+
+constexpr unsigned char NETFUN_INTEL_APP_OEM = 0x3E;
+
+enum IPMI_NETFN_INTEL_OEM_APP_CMD
+{
+    MDR_STATUS = 0x20,
+    MDR_COMPLETE = 0x21,
+    MDR_EVENT = 0x22,
+    MDR_READ = 0x23,
+    MDR_WRITE = 0x24,
+    MDR_LOCK = 0x25,
+    MDRII_AGENT_STATUS = 0x30,
+    MDRII_GET_DIR = 0x31,
+    MDRII_GET_DATA_INFO = 0x32,
+    MDRII_LOCK_DATA = 0x33,
+    MDRII_UNLOCK_DATA = 0x34,
+    MDRII_GET_DATA_BLOCK = 0x35,
+    MDRII_SEND_DIR = 0x38,
+    MDRII_SEND_DATA_INFO_OFFER = 0x39,
+    MDRII_SEND_DATA_INFO = 0x3a,
+    MDRII_DATA_START = 0x3b,
+    MDRII_DATA_DONE = 0x3c,
+    MDRII_SEND_DATA_BLOCK = 0x3d,
+};
+
+enum class IPMINetFnIntelOemGeneralCmds
+{
+    GetSmSignal = 0x14,
+    SetSmSignal = 0x15,
+    BmcControlServices = 0xC0,
+    SetSensorOverride = 0xEE,
+};
diff --git a/include/smbioshandler.hpp b/include/smbioshandler.hpp
new file mode 100644
index 0000000..4e403ca
--- /dev/null
+++ b/include/smbioshandler.hpp
@@ -0,0 +1,100 @@
+/*
+// Copyright (c) 2018 Intel Corporation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+
+#pragma once
+#include <cstddef>
+#include <cstdint>
+#include <oemcommands.hpp>
+
+#include "ipmid/api.h"
+
+constexpr uint16_t msgPayloadSize = 1024 * 60;
+
+typedef enum
+{
+    regionLockUnlocked = 0,
+    regionLockStrict,
+    regionLockPreemptable
+} MDRLockType;
+
+typedef struct
+{
+    uint8_t DirVer;
+    uint8_t MDRType;
+    uint16_t timestamp;
+    uint16_t DataSize;
+} __attribute__((packed)) MDRSmbios_Header;
+
+typedef struct
+{
+    uint8_t MdrVersion;
+    uint8_t regionId;
+    bool valid;
+    uint8_t updateCount;
+    uint8_t lockPolicy;
+    uint16_t regionLength;
+    uint16_t regionUsed;
+    uint8_t CRC8;
+} __attribute__((packed)) MDRState;
+
+struct RegionStatusRequest
+{
+    uint8_t regionId;
+} __attribute__((packed));
+
+struct RegionStatusResponse
+{
+    MDRState State;
+} __attribute__((packed));
+
+struct RegionCompleteRequest
+{
+    uint8_t sessionId;
+    uint8_t regionId;
+} __attribute__((packed));
+
+struct RegionReadRequest
+{
+    uint8_t regionId;
+    uint8_t length;
+    uint16_t offset;
+} __attribute__((packed));
+
+struct RegionReadResponse
+{
+    uint8_t length;
+    uint8_t updateCount;
+    uint8_t data[msgPayloadSize];
+} __attribute__((packed));
+
+struct RegionWriteRequest
+{
+    uint8_t sessionId;
+    uint8_t regionId;
+    uint8_t length;
+    uint16_t offset;
+    uint8_t data[msgPayloadSize];
+} __attribute__((packed));
+
+struct RegionLockRequest
+{
+    uint8_t sessionId;
+    uint8_t regionId;
+    uint8_t lockPolicy;
+    uint16_t msTimeout;
+} __attribute__((packed));
+
+constexpr size_t maxMDRId = 5;
diff --git a/include/smbiosmdrv2.hpp b/include/smbiosmdrv2.hpp
new file mode 100644
index 0000000..9736ee8
--- /dev/null
+++ b/include/smbiosmdrv2.hpp
@@ -0,0 +1,205 @@
+/*
+// Copyright (c) 2018 Intel Corporation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+
+#pragma once
+#include <ipmid/api.h>
+
+#include <oemcommands.hpp>
+
+constexpr uint8_t maxDirEntries = 4;
+constexpr uint16_t msgPayloadSize = 1024 * 60;
+constexpr uint32_t smbiosTableStorageSize = 64 * 1024;
+constexpr uint32_t mdriiSMSize = 0x00100000;
+
+struct DataIdStruct
+{
+    uint8_t dataInfo[16];
+} __attribute__((packed));
+
+struct Mdr2DirEntry
+{
+    DataIdStruct Id;
+    uint32_t size;
+    uint32_t dataSetSize;
+    uint32_t dataVersion;
+    uint32_t timestamp;
+} __attribute__((packed));
+
+// ====================== MDR II Pull Command Structures ======================
+// MDR II Pull Agent status inquiry command
+struct MDRiiGetAgentStatus
+{
+    uint16_t agentId;
+    uint8_t dirVersion;
+} __attribute__((packed));
+
+// MDR II status inquiry response
+struct MDRiiAgentStatusResponse
+{
+    uint8_t mdrVersion;
+    uint8_t agentVersion;
+    uint8_t dirVersion;
+    uint8_t dirEntries;
+    uint8_t dataRequest;
+} __attribute__((packed));
+
+// MDR II Pull Agent directory information inquiry command
+struct MDRiiGetDirRequest
+{
+    uint16_t agentId;
+    uint8_t dirIndex;
+} __attribute__((packed));
+
+// MDR II directory information inquiry response
+struct MDRiiGetDirResponse
+{
+    uint8_t mdrVersion;
+    uint8_t dirVersion;
+    uint8_t returnedEntries;
+    uint8_t remainingEntries;
+    uint8_t data[1];
+} __attribute__((packed));
+
+// MDR II Pull Agent data set information inquiry command
+struct MDRiiGetDataInfoRequest
+{
+    uint16_t agentId;
+    DataIdStruct dataSetInfo;
+} __attribute__((packed));
+
+// MDR II data set information inquiry response
+struct MDRiiGetDataInfoResponse
+{
+    uint8_t mdrVersion;
+    DataIdStruct dataSetId;
+    uint8_t validFlag;
+    uint32_t dataLength;
+    uint32_t dataVersion;
+    uint32_t timeStamp;
+} __attribute__((packed));
+
+// MDR II Pull Agent lock data set command
+struct MDRiiLockDataRequest
+{
+    uint16_t agentId;
+    DataIdStruct dataSetInfo;
+    uint16_t timeout;
+} __attribute__((packed));
+
+// MDR II Pull Agent lock data set response
+struct MDRiiLockDataResponse
+{
+    uint8_t mdrVersion;
+    uint16_t lockHandle;
+    uint32_t dataLength;
+    uint32_t xferAddress;
+    uint32_t xferLength;
+} __attribute__((packed));
+
+// MDR II Pull Agent unlock data set command
+struct MDRiiUnlockDataRequest
+{
+    uint16_t agentId;
+    uint16_t lockHandle;
+} __attribute__((packed));
+
+// MDR II Pull Agent get data block command
+struct MDRiiGetDataBlockRequest
+{
+    uint16_t agentId;
+    uint16_t lockHandle;
+    uint32_t xferOffset;
+    uint32_t xferLength;
+} __attribute__((packed));
+
+// MDR II Pull Agent get data block response
+struct MDRiiGetDataBlockResponse
+{
+    uint32_t xferLength;
+    uint32_t checksum;
+    uint8_t data[msgPayloadSize];
+} __attribute__((packed));
+
+// ====================== MDR II Push Command Structures ======================
+// MDR II Push Agent send dir info command
+struct MDRiiSendDirRequest
+{
+    uint16_t agentId;
+    uint8_t dirVersion;
+    uint8_t dirIndex;
+    uint8_t returnedEntries;
+    uint8_t remainingEntries;
+    Mdr2DirEntry data[1]; // place holder for N directory entries
+} __attribute__((packed));
+
+// MDR II Push Agent offer data set info command
+struct MDRiiOfferDataInfo
+{
+    uint16_t agentId;
+} __attribute__((packed));
+
+// MDR II Client send data set info offer response
+struct MDRiiOfferDataInfoResponse
+{
+    DataIdStruct dataSetInfo;
+} __attribute__((packed));
+
+// MDR II Push Agent send data set info command
+struct MDRiiSendDataInfoRequest
+{
+    uint16_t agentId;
+    DataIdStruct dataSetInfo;
+    uint8_t validFlag;
+    uint32_t dataLength;
+    uint32_t dataVersion; // Roughly equivalent to the "file name"
+    uint32_t
+        timeStamp; // More info on the identity of this particular set of data
+} __attribute__((packed));
+
+// MDR II Push Agent send data start command
+struct MDRiiDataStartRequest
+{
+    uint16_t agentId;
+    DataIdStruct dataSetInfo;
+    uint32_t dataLength;
+    uint32_t xferAddress;
+    uint32_t xferLength;
+    uint16_t timeout;
+} __attribute__((packed));
+
+// MDR II Client send data start response
+struct MDRiiDataStartResponse
+{
+    uint8_t xferStartAck;
+    uint16_t sessionHandle;
+} __attribute__((packed));
+
+// MDR II
+struct MDRiiDataDoneRequest
+{
+    uint16_t agentId;
+    uint16_t lockHandle;
+} __attribute__((packed));
+
+// MDR II Push Agent send data block command
+struct MDRiiSendDataBlockRequest
+{
+    uint16_t agentId;
+    uint16_t lockHandle;
+    uint32_t xferOffset;
+    uint32_t xferLength;
+    uint32_t checksum;
+} __attribute__((packed));
diff --git a/include/smbiosmdrv2handler.hpp b/include/smbiosmdrv2handler.hpp
new file mode 100644
index 0000000..636cbdb
--- /dev/null
+++ b/include/smbiosmdrv2handler.hpp
@@ -0,0 +1,401 @@
+/*
+// Copyright (c) 2018 Intel Corporation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+
+#pragma once
+#include <ipmid/api.h>
+#include <sys/mman.h>
+
+#include <oemcommands.hpp>
+#include <sdbusplus/timer.hpp>
+
+static constexpr const char *mdrType2File = "/var/lib/smbios/smbios2";
+static constexpr const char *smbiosPath = "/var/lib/smbios";
+static constexpr const size_t msgPayloadSize =
+    1024 * 60; // Total size will transfer for smbios table
+static constexpr const size_t mdriiSMSize = 0x00100000;
+
+static constexpr const uint16_t smbiosAgentId =
+    0x0101; // Agent ID for smbios entry
+static constexpr const int firstAgentIndex = 1;
+
+static constexpr const uint8_t maxDirEntries = 4; // Maximum directory entries
+static constexpr const uint32_t mdr2SMSize =
+    0x00100000; // Size of VGA share memory
+static constexpr const uint32_t mdr2SMBaseAddress =
+    0x9FF00000; // Base address of VGA share memory
+
+static constexpr const uint8_t mdrTypeII = 2; // MDR V2 type
+
+static constexpr const uint8_t mdr2Version = 2;        // MDR V2 versoin
+static constexpr const uint8_t smbiosAgentVersion = 1; // Agent version of
+                                                       // smbios
+
+static constexpr const uint32_t pageMask =
+    0xf000; // To make data become n times of page
+static constexpr const int smbiosDirIndex = 0; // SMBIOS directory index
+
+static constexpr const uint32_t smbiosTableVersion =
+    15; // Version of smbios table
+static constexpr const uint32_t smbiosTableTimestamp =
+    0x45464748; // Time stamp when smbios table created
+static constexpr const size_t smbiosSMMemoryOffset =
+    0; // Offset of VGA share memory
+static constexpr const size_t smbiosSMMemorySize =
+    1024 * 1024; // Total size of VGA share memory
+static constexpr const size_t smbiosTableStorageSize =
+    64 * 1024; // Total size of smbios table
+static constexpr const uint32_t defaultTimeout = 200;
+static constexpr const uint8_t sysClock = 100;
+static constexpr const int lastAgentIndex = -1;
+static constexpr const uint16_t lastAgentId = 0xFFFF;
+constexpr const uint32_t invalidChecksum = 0xffffffff;
+constexpr const char *dbusProperties = "org.freedesktop.DBus.Properties";
+constexpr const char *mdrv2Path = "/xyz/openbmc_project/Smbios/MDR_V2";
+constexpr const char *mdrv2Interface = "xyz.openbmc_project.Smbios.MDR_V2";
+
+enum class MDR2SMBIOSStatusEnum
+{
+    mdr2Init = 0,
+    mdr2Loaded = 1,
+    mdr2Updated = 2,
+    mdr2Updating = 3
+};
+
+enum class DirDataRequestEnum
+{
+    dirDataNotRequested = 0x00,
+    dirDataRequested = 0x01
+};
+
+enum MDR2DirLockEnum
+{
+    mdr2DirUnlock = 0,
+    mdr2DirLock = 1
+};
+
+#pragma pack(push)
+#pragma pack(1)
+
+struct MDRSMBIOSHeader
+{
+    uint8_t dirVer;
+    uint8_t mdrType;
+    uint32_t timestamp;
+    uint32_t dataSize;
+};
+
+struct DataIdStruct
+{
+    uint8_t dataInfo[16];
+};
+
+struct Mdr2DirEntry
+{
+    DataIdStruct id;
+    uint32_t size;
+    uint32_t dataSetSize;
+    uint32_t dataVersion;
+    uint32_t timestamp;
+};
+
+struct Mdr2DirLocalStruct
+{
+    Mdr2DirEntry common;
+    MDR2SMBIOSStatusEnum stage;
+    MDR2DirLockEnum lock;
+    uint16_t lockHandle;
+    uint32_t xferBuff;
+    uint32_t xferSize;
+    uint32_t maxDataSize;
+    uint8_t *dataStorage;
+};
+
+struct Mdr2DirStruct
+{
+    uint8_t agentVersion;
+    uint8_t dirVersion;
+    uint8_t dirEntries;
+    uint8_t status; // valid / locked / etc
+    uint8_t remoteDirVersion;
+    uint16_t sessionHandle;
+    Mdr2DirLocalStruct dir[maxDirEntries];
+};
+
+// Three members include dataSetSize, dataVersion and timestamp
+static constexpr const size_t syncDirCommonSize = 3;
+
+// ====================== MDR II Pull Command Structures ======================
+// MDR II Pull Agent status inquiry command
+struct MDRiiGetAgentStatus
+{
+    uint16_t agentId;
+    uint8_t dirVersion;
+};
+
+// MDR II status inquiry response
+struct MDRiiAgentStatusResponse
+{
+    uint8_t mdrVersion;
+    uint8_t agentVersion;
+    uint8_t dirVersion;
+    uint8_t dirEntries;
+    uint8_t dataRequest;
+};
+
+struct MDRiiGetDirRequest
+{
+    uint16_t agentId;
+    uint8_t dirIndex;
+};
+
+// MDR II directory information inquiry response
+struct MDRiiGetDirResponse
+{
+    uint8_t mdrVersion;
+    uint8_t dirVersion;
+    uint8_t returnedEntries;
+    uint8_t remainingEntries;
+    uint8_t data[1];
+};
+
+struct MDRiiGetDataInfoRequest
+{
+    uint16_t agentId;
+    DataIdStruct dataSetInfo;
+};
+
+// MDR II data set information inquiry response
+struct MDRiiGetDataInfoResponse
+{
+    uint8_t mdrVersion;
+    DataIdStruct dataSetId;
+    uint8_t validFlag;
+    uint32_t dataLength;
+    uint32_t dataVersion;
+    uint32_t timeStamp;
+};
+
+// MDR II Pull Agent get data block command
+struct MDRiiGetDataBlockRequest
+{
+    uint16_t agentId;
+    uint16_t lockHandle;
+    uint32_t xferOffset;
+    uint32_t xferLength;
+};
+
+// MDR II Pull Agent get data block response
+struct MDRiiGetDataBlockResponse
+{
+    uint32_t xferLength;
+    uint32_t checksum;
+    uint8_t data[msgPayloadSize];
+};
+
+// ====================== MDR II Push Command Structures ======================
+// MDR II Push Agent send dir info command
+struct MDRiiSendDirRequest
+{
+    uint16_t agentId;
+    uint8_t dirVersion;
+    uint8_t dirIndex;
+    uint8_t returnedEntries;
+    uint8_t remainingEntries;
+    Mdr2DirEntry data[1]; // place holder for N directory entries
+};
+
+struct MDRiiOfferDataInfo
+{
+    uint16_t agentId;
+};
+
+// MDR II Client send data set info offer response
+struct MDRiiOfferDataInfoResponse
+{
+    DataIdStruct dataSetInfo;
+};
+
+// MDR II Push Agent send data set info command
+struct MDRiiSendDataInfoRequest
+{
+    uint16_t agentId;
+    DataIdStruct dataSetInfo;
+    uint8_t validFlag;
+    uint32_t dataLength;
+    uint32_t dataVersion; // Roughly equivalent to the "file name"
+    uint32_t
+        timeStamp; // More info on the identity of this particular set of data
+};
+
+// MDR II Push Agent send data block command
+struct MDRiiSendDataBlockRequest
+{
+    uint16_t agentId;
+    uint16_t lockHandle;
+    uint32_t xferOffset;
+    uint32_t xferLength;
+    uint32_t checksum;
+};
+
+// MDR II Pull Agent lock data set command
+struct MDRiiLockDataRequest
+{
+    uint16_t agentId;
+    DataIdStruct dataSetInfo;
+    uint16_t timeout;
+};
+
+// MDR II Pull Agent lock data set response
+struct MDRiiLockDataResponse
+{
+    uint8_t mdrVersion;
+    uint16_t lockHandle;
+    uint32_t dataLength;
+    uint32_t xferAddress;
+    uint32_t xferLength;
+};
+
+// MDR II Pull Agent unlock data set command
+struct MDRiiUnlockDataRequest
+{
+    uint16_t agentId;
+    uint16_t lockHandle;
+};
+
+// MDR II Push Agent send data start command
+struct MDRiiDataStartRequest
+{
+    uint16_t agentId;
+    DataIdStruct dataSetInfo;
+    uint32_t dataLength;
+    uint32_t xferAddress;
+    uint32_t xferLength;
+    uint16_t timeout;
+};
+
+// MDR II Client send data start response
+struct MDRiiDataStartResponse
+{
+    uint8_t xferStartAck;
+    uint16_t sessionHandle;
+};
+
+// MDR II
+struct MDRiiDataDoneRequest
+{
+    uint16_t agentId;
+    uint16_t lockHandle;
+};
+
+#pragma pack(pop)
+
+class SharedMemoryArea
+{
+  public:
+    SharedMemoryArea(uint32_t addr, uint32_t areaSize) :
+        vPtr(nullptr), physicalAddr(addr), size(areaSize)
+    {
+        Initialize(addr, areaSize);
+    }
+
+    ~SharedMemoryArea()
+    {
+        if ((vPtr != nullptr) && (vPtr != MAP_FAILED))
+        {
+            if (0 != munmap(vPtr, size))
+            {
+                phosphor::logging::log<phosphor::logging::level::ERR>(
+                    "Ummap share memory failed");
+            }
+        }
+    }
+
+    void *vPtr;
+
+  private:
+    uint32_t physicalAddr;
+    uint32_t size;
+
+    void Initialize(uint32_t addr, uint32_t areaSize);
+};
+
+class MDRV2
+{
+  public:
+    MDRV2()
+    {
+        timer =
+            std::make_unique<phosphor::Timer>([&](void) { timeoutHandler(); });
+    }
+
+    int agentLookup(const uint16_t &agentId);
+    int findLockHandle(const uint16_t &lockHandle);
+    int syncDirCommonData(uint8_t idIndex, uint32_t size,
+                          const std::string &service);
+    int findDataId(const uint8_t *dataInfo, const size_t &len,
+                   const std::string &service);
+    uint16_t getSessionHandle(Mdr2DirStruct *dir);
+    bool smbiosIsUpdating(uint8_t index);
+    uint32_t calcChecksum32(uint8_t *buf, uint32_t len);
+    bool storeDatatoFlash(MDRSMBIOSHeader *mdrHdr, uint8_t *data);
+    bool smbiosUnlock(uint8_t index);
+    void timeoutHandler();
+    bool smbiosTryLock(uint8_t flag, uint8_t index, uint16_t *session,
+                       uint16_t timeout);
+    int sdplusMdrv2GetProperty(const std::string &name,
+                               sdbusplus::message::variant<uint8_t> &value,
+                               const std::string &service);
+
+    Mdr2DirStruct smbiosDir{smbiosAgentVersion,
+                            1,
+                            1,
+                            1,
+                            0,
+                            0,
+                            {40,
+                             41,
+                             42,
+                             43,
+                             44,
+                             45,
+                             46,
+                             47,
+                             48,
+                             49,
+                             50,
+                             51,
+                             52,
+                             53,
+                             54,
+                             0x42,
+                             0,
+                             smbiosTableStorageSize,
+                             smbiosTableVersion,
+                             smbiosTableTimestamp,
+                             MDR2SMBIOSStatusEnum::mdr2Init,
+                             MDR2DirLockEnum::mdr2DirUnlock,
+                             0,
+                             smbiosSMMemoryOffset,
+                             smbiosSMMemorySize,
+                             smbiosTableStorageSize,
+                             smbiosTableStorage}};
+    std::unique_ptr<SharedMemoryArea> area;
+    std::unique_ptr<phosphor::Timer> timer;
+
+  private:
+    uint8_t lockIndex = 0;
+    uint8_t smbiosTableStorage[smbiosTableStorageSize];
+};
diff --git a/include/variantvisitors.hpp b/include/variantvisitors.hpp
new file mode 100644
index 0000000..f8dbb0c
--- /dev/null
+++ b/include/variantvisitors.hpp
@@ -0,0 +1,27 @@
+/*
+// Copyright (c) 2017 Intel Corporation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+
+#pragma once
+#include <cstdint>
+#include <limits>
+#include <sdbusplus/bus.hpp>
+namespace ipmi
+{
+
+using DbusVariant =
+    sdbusplus::message::variant<std::string, bool, uint8_t, uint16_t, int16_t,
+                                uint32_t, int32_t, uint64_t, int64_t, double>;
+} // namespace ipmi
diff --git a/non-yocto/phosphor-logging/elog-errors.hpp b/non-yocto/phosphor-logging/elog-errors.hpp
new file mode 100644
index 0000000..b87236a
--- /dev/null
+++ b/non-yocto/phosphor-logging/elog-errors.hpp
@@ -0,0 +1,2528 @@
+// This file was autogenerated.  Do not edit!
+// See elog-gen.py for more details
+#pragma once
+
+#include <phosphor-logging/elog.hpp>
+#include <phosphor-logging/log.hpp>
+#include <sdbusplus/exception.hpp>
+#include <string>
+#include <tuple>
+#include <type_traits>
+
+namespace sdbusplus
+{
+namespace xyz
+{
+namespace openbmc_project
+{
+namespace Dump
+{
+namespace Create
+{
+namespace Error
+{
+struct QuotaExceeded;
+} // namespace Error
+} // namespace Create
+} // namespace Dump
+} // namespace openbmc_project
+} // namespace xyz
+} // namespace sdbusplus
+
+namespace sdbusplus
+{
+namespace xyz
+{
+namespace openbmc_project
+{
+namespace State
+{
+namespace Shutdown
+{
+namespace Inventory
+{
+namespace Error
+{
+struct Fan;
+} // namespace Error
+} // namespace Inventory
+} // namespace Shutdown
+} // namespace State
+} // namespace openbmc_project
+} // namespace xyz
+} // namespace sdbusplus
+
+namespace sdbusplus
+{
+namespace xyz
+{
+namespace openbmc_project
+{
+namespace Common
+{
+namespace Device
+{
+namespace Error
+{
+struct ReadFailure;
+} // namespace Error
+} // namespace Device
+} // namespace Common
+} // namespace openbmc_project
+} // namespace xyz
+} // namespace sdbusplus
+
+namespace sdbusplus
+{
+namespace xyz
+{
+namespace openbmc_project
+{
+namespace State
+{
+namespace Host
+{
+namespace Error
+{
+struct SoftOffTimeout;
+} // namespace Error
+} // namespace Host
+} // namespace State
+} // namespace openbmc_project
+} // namespace xyz
+} // namespace sdbusplus
+
+namespace sdbusplus
+{
+namespace xyz
+{
+namespace openbmc_project
+{
+namespace Common
+{
+namespace File
+{
+namespace Error
+{
+struct Open;
+} // namespace Error
+} // namespace File
+} // namespace Common
+} // namespace openbmc_project
+} // namespace xyz
+} // namespace sdbusplus
+
+namespace sdbusplus
+{
+namespace xyz
+{
+namespace openbmc_project
+{
+namespace Inventory
+{
+namespace Error
+{
+struct Nonfunctional;
+} // namespace Error
+} // namespace Inventory
+} // namespace openbmc_project
+} // namespace xyz
+} // namespace sdbusplus
+
+namespace sdbusplus
+{
+namespace xyz
+{
+namespace openbmc_project
+{
+namespace Control
+{
+namespace Device
+{
+namespace Error
+{
+struct WriteFailure;
+} // namespace Error
+} // namespace Device
+} // namespace Control
+} // namespace openbmc_project
+} // namespace xyz
+} // namespace sdbusplus
+
+namespace sdbusplus
+{
+namespace xyz
+{
+namespace openbmc_project
+{
+namespace Common
+{
+namespace File
+{
+namespace Error
+{
+struct Seek;
+} // namespace Error
+} // namespace File
+} // namespace Common
+} // namespace openbmc_project
+} // namespace xyz
+} // namespace sdbusplus
+
+namespace sdbusplus
+{
+namespace xyz
+{
+namespace openbmc_project
+{
+namespace User
+{
+namespace Common
+{
+namespace Error
+{
+struct UserNameDoesNotExist;
+} // namespace Error
+} // namespace Common
+} // namespace User
+} // namespace openbmc_project
+} // namespace xyz
+} // namespace sdbusplus
+
+namespace sdbusplus
+{
+namespace xyz
+{
+namespace openbmc_project
+{
+namespace Common
+{
+namespace File
+{
+namespace Error
+{
+struct Write;
+} // namespace Error
+} // namespace File
+} // namespace Common
+} // namespace openbmc_project
+} // namespace xyz
+} // namespace sdbusplus
+
+namespace sdbusplus
+{
+namespace xyz
+{
+namespace openbmc_project
+{
+namespace Inventory
+{
+namespace Error
+{
+struct NotPresent;
+} // namespace Error
+} // namespace Inventory
+} // namespace openbmc_project
+} // namespace xyz
+} // namespace sdbusplus
+
+namespace sdbusplus
+{
+namespace xyz
+{
+namespace openbmc_project
+{
+namespace Common
+{
+namespace Error
+{
+struct InternalFailure;
+} // namespace Error
+} // namespace Common
+} // namespace openbmc_project
+} // namespace xyz
+} // namespace sdbusplus
+
+namespace sdbusplus
+{
+namespace xyz
+{
+namespace openbmc_project
+{
+namespace Common
+{
+namespace Callout
+{
+namespace Error
+{
+struct Device;
+} // namespace Error
+} // namespace Callout
+} // namespace Common
+} // namespace openbmc_project
+} // namespace xyz
+} // namespace sdbusplus
+
+namespace sdbusplus
+{
+namespace xyz
+{
+namespace openbmc_project
+{
+namespace Sensor
+{
+namespace Threshold
+{
+namespace Error
+{
+struct CriticalLow;
+} // namespace Error
+} // namespace Threshold
+} // namespace Sensor
+} // namespace openbmc_project
+} // namespace xyz
+} // namespace sdbusplus
+
+namespace sdbusplus
+{
+namespace xyz
+{
+namespace openbmc_project
+{
+namespace Sensor
+{
+namespace Threshold
+{
+namespace Error
+{
+struct CriticalHigh;
+} // namespace Error
+} // namespace Threshold
+} // namespace Sensor
+} // namespace openbmc_project
+} // namespace xyz
+} // namespace sdbusplus
+
+namespace sdbusplus
+{
+namespace xyz
+{
+namespace openbmc_project
+{
+namespace Sensor
+{
+namespace Device
+{
+namespace Error
+{
+struct ReadFailure;
+} // namespace Error
+} // namespace Device
+} // namespace Sensor
+} // namespace openbmc_project
+} // namespace xyz
+} // namespace sdbusplus
+
+namespace sdbusplus
+{
+namespace xyz
+{
+namespace openbmc_project
+{
+namespace Control
+{
+namespace Host
+{
+namespace Error
+{
+struct CommandNotSupported;
+} // namespace Error
+} // namespace Host
+} // namespace Control
+} // namespace openbmc_project
+} // namespace xyz
+} // namespace sdbusplus
+
+namespace sdbusplus
+{
+namespace xyz
+{
+namespace openbmc_project
+{
+namespace User
+{
+namespace Common
+{
+namespace Error
+{
+struct UserNameGrpPrivFail;
+} // namespace Error
+} // namespace Common
+} // namespace User
+} // namespace openbmc_project
+} // namespace xyz
+} // namespace sdbusplus
+
+namespace sdbusplus
+{
+namespace xyz
+{
+namespace openbmc_project
+{
+namespace Common
+{
+namespace Callout
+{
+namespace Error
+{
+struct GPIO;
+} // namespace Error
+} // namespace Callout
+} // namespace Common
+} // namespace openbmc_project
+} // namespace xyz
+} // namespace sdbusplus
+
+namespace sdbusplus
+{
+namespace xyz
+{
+namespace openbmc_project
+{
+namespace Common
+{
+namespace Error
+{
+struct InvalidArgument;
+} // namespace Error
+} // namespace Common
+} // namespace openbmc_project
+} // namespace xyz
+} // namespace sdbusplus
+
+namespace sdbusplus
+{
+namespace xyz
+{
+namespace openbmc_project
+{
+namespace User
+{
+namespace Common
+{
+namespace Error
+{
+struct NoResource;
+} // namespace Error
+} // namespace Common
+} // namespace User
+} // namespace openbmc_project
+} // namespace xyz
+} // namespace sdbusplus
+
+namespace sdbusplus
+{
+namespace xyz
+{
+namespace openbmc_project
+{
+namespace Common
+{
+namespace Device
+{
+namespace Error
+{
+struct WriteFailure;
+} // namespace Error
+} // namespace Device
+} // namespace Common
+} // namespace openbmc_project
+} // namespace xyz
+} // namespace sdbusplus
+
+namespace sdbusplus
+{
+namespace xyz
+{
+namespace openbmc_project
+{
+namespace Common
+{
+namespace Error
+{
+struct InsufficientPermission;
+} // namespace Error
+} // namespace Common
+} // namespace openbmc_project
+} // namespace xyz
+} // namespace sdbusplus
+
+namespace sdbusplus
+{
+namespace xyz
+{
+namespace openbmc_project
+{
+namespace Dump
+{
+namespace Create
+{
+namespace Error
+{
+struct Disabled;
+} // namespace Error
+} // namespace Create
+} // namespace Dump
+} // namespace openbmc_project
+} // namespace xyz
+} // namespace sdbusplus
+
+namespace sdbusplus
+{
+namespace xyz
+{
+namespace openbmc_project
+{
+namespace Common
+{
+namespace Callout
+{
+namespace Error
+{
+struct IPMISensor;
+} // namespace Error
+} // namespace Callout
+} // namespace Common
+} // namespace openbmc_project
+} // namespace xyz
+} // namespace sdbusplus
+
+namespace sdbusplus
+{
+namespace xyz
+{
+namespace openbmc_project
+{
+namespace Common
+{
+namespace Error
+{
+struct Timeout;
+} // namespace Error
+} // namespace Common
+} // namespace openbmc_project
+} // namespace xyz
+} // namespace sdbusplus
+
+namespace sdbusplus
+{
+namespace xyz
+{
+namespace openbmc_project
+{
+namespace Common
+{
+namespace Callout
+{
+namespace Error
+{
+struct Inventory;
+} // namespace Error
+} // namespace Callout
+} // namespace Common
+} // namespace openbmc_project
+} // namespace xyz
+} // namespace sdbusplus
+
+namespace sdbusplus
+{
+namespace xyz
+{
+namespace openbmc_project
+{
+namespace Common
+{
+namespace Callout
+{
+namespace Error
+{
+struct IIC;
+} // namespace Error
+} // namespace Callout
+} // namespace Common
+} // namespace openbmc_project
+} // namespace xyz
+} // namespace sdbusplus
+
+namespace sdbusplus
+{
+namespace xyz
+{
+namespace openbmc_project
+{
+namespace State
+{
+namespace Shutdown
+{
+namespace ThermalEvent
+{
+namespace Error
+{
+struct GPU;
+} // namespace Error
+} // namespace ThermalEvent
+} // namespace Shutdown
+} // namespace State
+} // namespace openbmc_project
+} // namespace xyz
+} // namespace sdbusplus
+
+namespace sdbusplus
+{
+namespace xyz
+{
+namespace openbmc_project
+{
+namespace State
+{
+namespace Shutdown
+{
+namespace Power
+{
+namespace Error
+{
+struct Fault;
+} // namespace Error
+} // namespace Power
+} // namespace Shutdown
+} // namespace State
+} // namespace openbmc_project
+} // namespace xyz
+} // namespace sdbusplus
+
+namespace sdbusplus
+{
+namespace xyz
+{
+namespace openbmc_project
+{
+namespace User
+{
+namespace Common
+{
+namespace Error
+{
+struct UserNameExists;
+} // namespace Error
+} // namespace Common
+} // namespace User
+} // namespace openbmc_project
+} // namespace xyz
+} // namespace sdbusplus
+
+namespace sdbusplus
+{
+namespace xyz
+{
+namespace openbmc_project
+{
+namespace State
+{
+namespace Shutdown
+{
+namespace ThermalEvent
+{
+namespace Error
+{
+struct Processor;
+} // namespace Error
+} // namespace ThermalEvent
+} // namespace Shutdown
+} // namespace State
+} // namespace openbmc_project
+} // namespace xyz
+} // namespace sdbusplus
+
+namespace phosphor
+{
+
+namespace logging
+{
+
+namespace xyz
+{
+namespace openbmc_project
+{
+namespace Control
+{
+namespace Host
+{
+namespace _CommandNotSupported
+{
+
+} // namespace _CommandNotSupported
+
+struct CommandNotSupported
+{
+    static constexpr auto L = level::ERR;
+    using metadata_types = std::tuple<>;
+};
+
+} // namespace Host
+} // namespace Control
+} // namespace openbmc_project
+} // namespace xyz
+
+namespace details
+{
+
+template <>
+struct map_exception_type<
+    sdbusplus::xyz::openbmc_project::Control::Host::Error::CommandNotSupported>
+{
+    using type = xyz::openbmc_project::Control::Host::CommandNotSupported;
+};
+
+} // namespace details
+
+namespace xyz
+{
+namespace openbmc_project
+{
+namespace Sensor
+{
+namespace Threshold
+{
+namespace _CriticalHigh
+{
+
+struct SENSOR_DATA
+{
+    static constexpr auto str = "SENSOR_DATA=%s";
+    static constexpr auto str_short = "SENSOR_DATA";
+    using type = std::tuple<std::decay_t<decltype(str)>, const char*>;
+    explicit constexpr SENSOR_DATA(const char* a) : _entry(entry(str, a)){};
+    type _entry;
+};
+
+} // namespace _CriticalHigh
+
+struct CriticalHigh
+{
+    static constexpr auto L = level::ERR;
+    using SENSOR_DATA = _CriticalHigh::SENSOR_DATA;
+    using metadata_types = std::tuple<SENSOR_DATA>;
+};
+
+} // namespace Threshold
+} // namespace Sensor
+} // namespace openbmc_project
+} // namespace xyz
+
+namespace details
+{
+
+template <>
+struct map_exception_type<
+    sdbusplus::xyz::openbmc_project::Sensor::Threshold::Error::CriticalHigh>
+{
+    using type = xyz::openbmc_project::Sensor::Threshold::CriticalHigh;
+};
+
+} // namespace details
+
+namespace xyz
+{
+namespace openbmc_project
+{
+namespace Sensor
+{
+namespace Threshold
+{
+namespace _CriticalLow
+{
+
+struct SENSOR_DATA
+{
+    static constexpr auto str = "SENSOR_DATA=%s";
+    static constexpr auto str_short = "SENSOR_DATA";
+    using type = std::tuple<std::decay_t<decltype(str)>, const char*>;
+    explicit constexpr SENSOR_DATA(const char* a) : _entry(entry(str, a)){};
+    type _entry;
+};
+
+} // namespace _CriticalLow
+
+struct CriticalLow
+{
+    static constexpr auto L = level::ERR;
+    using SENSOR_DATA = _CriticalLow::SENSOR_DATA;
+    using metadata_types = std::tuple<SENSOR_DATA>;
+};
+
+} // namespace Threshold
+} // namespace Sensor
+} // namespace openbmc_project
+} // namespace xyz
+
+namespace details
+{
+
+template <>
+struct map_exception_type<
+    sdbusplus::xyz::openbmc_project::Sensor::Threshold::Error::CriticalLow>
+{
+    using type = xyz::openbmc_project::Sensor::Threshold::CriticalLow;
+};
+
+} // namespace details
+
+namespace xyz
+{
+namespace openbmc_project
+{
+namespace State
+{
+namespace Shutdown
+{
+namespace ThermalEvent
+{
+namespace _Processor
+{
+
+} // namespace _Processor
+
+struct Processor
+{
+    static constexpr auto L = level::ERR;
+    using metadata_types = std::tuple<>;
+};
+
+} // namespace ThermalEvent
+} // namespace Shutdown
+} // namespace State
+} // namespace openbmc_project
+} // namespace xyz
+
+namespace details
+{
+
+template <>
+struct map_exception_type<sdbusplus::xyz::openbmc_project::State::Shutdown::
+                              ThermalEvent::Error::Processor>
+{
+    using type = xyz::openbmc_project::State::Shutdown::ThermalEvent::Processor;
+};
+
+} // namespace details
+
+namespace xyz
+{
+namespace openbmc_project
+{
+namespace State
+{
+namespace Shutdown
+{
+namespace ThermalEvent
+{
+namespace _GPU
+{
+
+} // namespace _GPU
+
+struct GPU
+{
+    static constexpr auto L = level::ERR;
+    using metadata_types = std::tuple<>;
+};
+
+} // namespace ThermalEvent
+} // namespace Shutdown
+} // namespace State
+} // namespace openbmc_project
+} // namespace xyz
+
+namespace details
+{
+
+template <>
+struct map_exception_type<
+    sdbusplus::xyz::openbmc_project::State::Shutdown::ThermalEvent::Error::GPU>
+{
+    using type = xyz::openbmc_project::State::Shutdown::ThermalEvent::GPU;
+};
+
+} // namespace details
+
+namespace xyz
+{
+namespace openbmc_project
+{
+namespace Dump
+{
+namespace Create
+{
+namespace _Disabled
+{
+
+} // namespace _Disabled
+
+struct Disabled
+{
+    static constexpr auto L = level::ERR;
+    using metadata_types = std::tuple<>;
+};
+
+} // namespace Create
+} // namespace Dump
+} // namespace openbmc_project
+} // namespace xyz
+
+namespace details
+{
+
+template <>
+struct map_exception_type<
+    sdbusplus::xyz::openbmc_project::Dump::Create::Error::Disabled>
+{
+    using type = xyz::openbmc_project::Dump::Create::Disabled;
+};
+
+} // namespace details
+
+namespace xyz
+{
+namespace openbmc_project
+{
+namespace Dump
+{
+namespace Create
+{
+namespace _QuotaExceeded
+{
+
+struct REASON
+{
+    static constexpr auto str = "REASON = %s";
+    static constexpr auto str_short = "REASON ";
+    using type = std::tuple<std::decay_t<decltype(str)>, const char*>;
+    explicit constexpr REASON(const char* a) : _entry(entry(str, a)){};
+    type _entry;
+};
+
+} // namespace _QuotaExceeded
+
+struct QuotaExceeded
+{
+    static constexpr auto L = level::ERR;
+    using REASON = _QuotaExceeded::REASON;
+    using metadata_types = std::tuple<REASON>;
+};
+
+} // namespace Create
+} // namespace Dump
+} // namespace openbmc_project
+} // namespace xyz
+
+namespace details
+{
+
+template <>
+struct map_exception_type<
+    sdbusplus::xyz::openbmc_project::Dump::Create::Error::QuotaExceeded>
+{
+    using type = xyz::openbmc_project::Dump::Create::QuotaExceeded;
+};
+
+} // namespace details
+
+namespace xyz
+{
+namespace openbmc_project
+{
+namespace Common
+{
+namespace _Timeout
+{
+
+struct TIMEOUT_IN_MSEC
+{
+    static constexpr auto str = "TIMEOUT_IN_MSEC=%llu";
+    static constexpr auto str_short = "TIMEOUT_IN_MSEC";
+    using type = std::tuple<std::decay_t<decltype(str)>, uint64_t>;
+    explicit constexpr TIMEOUT_IN_MSEC(uint64_t a) : _entry(entry(str, a)){};
+    type _entry;
+};
+
+} // namespace _Timeout
+
+struct Timeout
+{
+    static constexpr auto L = level::ERR;
+    using TIMEOUT_IN_MSEC = _Timeout::TIMEOUT_IN_MSEC;
+    using metadata_types = std::tuple<TIMEOUT_IN_MSEC>;
+};
+
+} // namespace Common
+} // namespace openbmc_project
+} // namespace xyz
+
+namespace details
+{
+
+template <>
+struct map_exception_type<
+    sdbusplus::xyz::openbmc_project::Common::Error::Timeout>
+{
+    using type = xyz::openbmc_project::Common::Timeout;
+};
+
+} // namespace details
+
+namespace xyz
+{
+namespace openbmc_project
+{
+namespace Common
+{
+namespace _InternalFailure
+{
+
+} // namespace _InternalFailure
+
+struct InternalFailure
+{
+    static constexpr auto L = level::ERR;
+    using metadata_types = std::tuple<>;
+};
+
+} // namespace Common
+} // namespace openbmc_project
+} // namespace xyz
+
+namespace details
+{
+
+template <>
+struct map_exception_type<
+    sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure>
+{
+    using type = xyz::openbmc_project::Common::InternalFailure;
+};
+
+} // namespace details
+
+namespace xyz
+{
+namespace openbmc_project
+{
+namespace Common
+{
+namespace _InvalidArgument
+{
+
+struct ARGUMENT_NAME
+{
+    static constexpr auto str = "ARGUMENT_NAME=%s";
+    static constexpr auto str_short = "ARGUMENT_NAME";
+    using type = std::tuple<std::decay_t<decltype(str)>, const char*>;
+    explicit constexpr ARGUMENT_NAME(const char* a) : _entry(entry(str, a)){};
+    type _entry;
+};
+struct ARGUMENT_VALUE
+{
+    static constexpr auto str = "ARGUMENT_VALUE=%s";
+    static constexpr auto str_short = "ARGUMENT_VALUE";
+    using type = std::tuple<std::decay_t<decltype(str)>, const char*>;
+    explicit constexpr ARGUMENT_VALUE(const char* a) : _entry(entry(str, a)){};
+    type _entry;
+};
+
+} // namespace _InvalidArgument
+
+struct InvalidArgument
+{
+    static constexpr auto L = level::ERR;
+    using ARGUMENT_NAME = _InvalidArgument::ARGUMENT_NAME;
+    using ARGUMENT_VALUE = _InvalidArgument::ARGUMENT_VALUE;
+    using metadata_types = std::tuple<ARGUMENT_NAME, ARGUMENT_VALUE>;
+};
+
+} // namespace Common
+} // namespace openbmc_project
+} // namespace xyz
+
+namespace details
+{
+
+template <>
+struct map_exception_type<
+    sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument>
+{
+    using type = xyz::openbmc_project::Common::InvalidArgument;
+};
+
+} // namespace details
+
+namespace xyz
+{
+namespace openbmc_project
+{
+namespace Common
+{
+namespace _InsufficientPermission
+{
+
+} // namespace _InsufficientPermission
+
+struct InsufficientPermission
+{
+    static constexpr auto L = level::INFO;
+    using metadata_types = std::tuple<>;
+};
+
+} // namespace Common
+} // namespace openbmc_project
+} // namespace xyz
+
+namespace details
+{
+
+template <>
+struct map_exception_type<
+    sdbusplus::xyz::openbmc_project::Common::Error::InsufficientPermission>
+{
+    using type = xyz::openbmc_project::Common::InsufficientPermission;
+};
+
+} // namespace details
+
+namespace xyz
+{
+namespace openbmc_project
+{
+namespace User
+{
+namespace Common
+{
+namespace _UserNameExists
+{
+
+} // namespace _UserNameExists
+
+struct UserNameExists
+{
+    static constexpr auto L = level::ERR;
+    using metadata_types = std::tuple<>;
+};
+
+} // namespace Common
+} // namespace User
+} // namespace openbmc_project
+} // namespace xyz
+
+namespace details
+{
+
+template <>
+struct map_exception_type<
+    sdbusplus::xyz::openbmc_project::User::Common::Error::UserNameExists>
+{
+    using type = xyz::openbmc_project::User::Common::UserNameExists;
+};
+
+} // namespace details
+
+namespace xyz
+{
+namespace openbmc_project
+{
+namespace User
+{
+namespace Common
+{
+namespace _UserNameDoesNotExist
+{
+
+} // namespace _UserNameDoesNotExist
+
+struct UserNameDoesNotExist
+{
+    static constexpr auto L = level::ERR;
+    using metadata_types = std::tuple<>;
+};
+
+} // namespace Common
+} // namespace User
+} // namespace openbmc_project
+} // namespace xyz
+
+namespace details
+{
+
+template <>
+struct map_exception_type<
+    sdbusplus::xyz::openbmc_project::User::Common::Error::UserNameDoesNotExist>
+{
+    using type = xyz::openbmc_project::User::Common::UserNameDoesNotExist;
+};
+
+} // namespace details
+
+namespace xyz
+{
+namespace openbmc_project
+{
+namespace User
+{
+namespace Common
+{
+namespace _UserNameGrpPrivFail
+{
+
+struct REASON
+{
+    static constexpr auto str = "REASON = %s";
+    static constexpr auto str_short = "REASON ";
+    using type = std::tuple<std::decay_t<decltype(str)>, const char*>;
+    explicit constexpr REASON(const char* a) : _entry(entry(str, a)){};
+    type _entry;
+};
+
+} // namespace _UserNameGrpPrivFail
+
+struct UserNameGrpPrivFail
+{
+    static constexpr auto L = level::ERR;
+    using REASON = _UserNameGrpPrivFail::REASON;
+    using metadata_types = std::tuple<REASON>;
+};
+
+} // namespace Common
+} // namespace User
+} // namespace openbmc_project
+} // namespace xyz
+
+namespace details
+{
+
+template <>
+struct map_exception_type<
+    sdbusplus::xyz::openbmc_project::User::Common::Error::UserNameGrpPrivFail>
+{
+    using type = xyz::openbmc_project::User::Common::UserNameGrpPrivFail;
+};
+
+} // namespace details
+
+namespace xyz
+{
+namespace openbmc_project
+{
+namespace User
+{
+namespace Common
+{
+namespace _NoResource
+{
+
+struct REASON
+{
+    static constexpr auto str = "REASON = %s";
+    static constexpr auto str_short = "REASON ";
+    using type = std::tuple<std::decay_t<decltype(str)>, const char*>;
+    explicit constexpr REASON(const char* a) : _entry(entry(str, a)){};
+    type _entry;
+};
+
+} // namespace _NoResource
+
+struct NoResource
+{
+    static constexpr auto L = level::ERR;
+    using REASON = _NoResource::REASON;
+    using metadata_types = std::tuple<REASON>;
+};
+
+} // namespace Common
+} // namespace User
+} // namespace openbmc_project
+} // namespace xyz
+
+namespace details
+{
+
+template <>
+struct map_exception_type<
+    sdbusplus::xyz::openbmc_project::User::Common::Error::NoResource>
+{
+    using type = xyz::openbmc_project::User::Common::NoResource;
+};
+
+} // namespace details
+
+namespace xyz
+{
+namespace openbmc_project
+{
+namespace Common
+{
+namespace File
+{
+namespace _Open
+{
+
+struct ERRNO
+{
+    static constexpr auto str = "ERRNO=%d";
+    static constexpr auto str_short = "ERRNO";
+    using type = std::tuple<std::decay_t<decltype(str)>, int32_t>;
+    explicit constexpr ERRNO(int32_t a) : _entry(entry(str, a)){};
+    type _entry;
+};
+struct PATH
+{
+    static constexpr auto str = "PATH=%s";
+    static constexpr auto str_short = "PATH";
+    using type = std::tuple<std::decay_t<decltype(str)>, const char*>;
+    explicit constexpr PATH(const char* a) : _entry(entry(str, a)){};
+    type _entry;
+};
+
+} // namespace _Open
+
+struct Open
+{
+    static constexpr auto L = level::ERR;
+    using ERRNO = _Open::ERRNO;
+    using PATH = _Open::PATH;
+    using metadata_types = std::tuple<ERRNO, PATH>;
+};
+
+} // namespace File
+} // namespace Common
+} // namespace openbmc_project
+} // namespace xyz
+
+namespace details
+{
+
+template <>
+struct map_exception_type<
+    sdbusplus::xyz::openbmc_project::Common::File::Error::Open>
+{
+    using type = xyz::openbmc_project::Common::File::Open;
+};
+
+} // namespace details
+
+namespace xyz
+{
+namespace openbmc_project
+{
+namespace Common
+{
+namespace File
+{
+namespace _Seek
+{
+
+struct OFFSET
+{
+    static constexpr auto str = "OFFSET=%ll";
+    static constexpr auto str_short = "OFFSET";
+    using type = std::tuple<std::decay_t<decltype(str)>, int64_t>;
+    explicit constexpr OFFSET(int64_t a) : _entry(entry(str, a)){};
+    type _entry;
+};
+struct WHENCE
+{
+    static constexpr auto str = "WHENCE=%d";
+    static constexpr auto str_short = "WHENCE";
+    using type = std::tuple<std::decay_t<decltype(str)>, int32_t>;
+    explicit constexpr WHENCE(int32_t a) : _entry(entry(str, a)){};
+    type _entry;
+};
+struct ERRNO
+{
+    static constexpr auto str = "ERRNO=%d";
+    static constexpr auto str_short = "ERRNO";
+    using type = std::tuple<std::decay_t<decltype(str)>, int32_t>;
+    explicit constexpr ERRNO(int32_t a) : _entry(entry(str, a)){};
+    type _entry;
+};
+struct PATH
+{
+    static constexpr auto str = "PATH=%s";
+    static constexpr auto str_short = "PATH";
+    using type = std::tuple<std::decay_t<decltype(str)>, const char*>;
+    explicit constexpr PATH(const char* a) : _entry(entry(str, a)){};
+    type _entry;
+};
+
+} // namespace _Seek
+
+struct Seek
+{
+    static constexpr auto L = level::ERR;
+    using OFFSET = _Seek::OFFSET;
+    using WHENCE = _Seek::WHENCE;
+    using ERRNO = _Seek::ERRNO;
+    using PATH = _Seek::PATH;
+    using metadata_types = std::tuple<OFFSET, WHENCE, ERRNO, PATH>;
+};
+
+} // namespace File
+} // namespace Common
+} // namespace openbmc_project
+} // namespace xyz
+
+namespace details
+{
+
+template <>
+struct map_exception_type<
+    sdbusplus::xyz::openbmc_project::Common::File::Error::Seek>
+{
+    using type = xyz::openbmc_project::Common::File::Seek;
+};
+
+} // namespace details
+
+namespace xyz
+{
+namespace openbmc_project
+{
+namespace Common
+{
+namespace File
+{
+namespace _Write
+{
+
+struct ERRNO
+{
+    static constexpr auto str = "ERRNO=%d";
+    static constexpr auto str_short = "ERRNO";
+    using type = std::tuple<std::decay_t<decltype(str)>, int32_t>;
+    explicit constexpr ERRNO(int32_t a) : _entry(entry(str, a)){};
+    type _entry;
+};
+struct PATH
+{
+    static constexpr auto str = "PATH=%s";
+    static constexpr auto str_short = "PATH";
+    using type = std::tuple<std::decay_t<decltype(str)>, const char*>;
+    explicit constexpr PATH(const char* a) : _entry(entry(str, a)){};
+    type _entry;
+};
+
+} // namespace _Write
+
+struct Write
+{
+    static constexpr auto L = level::ERR;
+    using ERRNO = _Write::ERRNO;
+    using PATH = _Write::PATH;
+    using metadata_types = std::tuple<ERRNO, PATH>;
+};
+
+} // namespace File
+} // namespace Common
+} // namespace openbmc_project
+} // namespace xyz
+
+namespace details
+{
+
+template <>
+struct map_exception_type<
+    sdbusplus::xyz::openbmc_project::Common::File::Error::Write>
+{
+    using type = xyz::openbmc_project::Common::File::Write;
+};
+
+} // namespace details
+
+namespace example
+{
+namespace xyz
+{
+namespace openbmc_project
+{
+namespace Example
+{
+namespace Device
+{
+namespace _Callout
+{
+
+struct CALLOUT_ERRNO_TEST
+{
+    static constexpr auto str = "CALLOUT_ERRNO_TEST=%d";
+    static constexpr auto str_short = "CALLOUT_ERRNO_TEST";
+    using type = std::tuple<std::decay_t<decltype(str)>, int32_t>;
+    explicit constexpr CALLOUT_ERRNO_TEST(int32_t a) : _entry(entry(str, a)){};
+    type _entry;
+};
+struct CALLOUT_DEVICE_PATH_TEST
+{
+    static constexpr auto str = "CALLOUT_DEVICE_PATH_TEST=%s";
+    static constexpr auto str_short = "CALLOUT_DEVICE_PATH_TEST";
+    using type = std::tuple<std::decay_t<decltype(str)>, const char*>;
+    explicit constexpr CALLOUT_DEVICE_PATH_TEST(const char* a) :
+        _entry(entry(str, a)){};
+    type _entry;
+};
+
+} // namespace _Callout
+
+struct Callout : public sdbusplus::exception_t
+{
+    static constexpr auto errName =
+        "example.xyz.openbmc_project.Example.Device.Callout";
+    static constexpr auto errDesc = "Generic device callout";
+    static constexpr auto L = level::ERR;
+    using CALLOUT_ERRNO_TEST = _Callout::CALLOUT_ERRNO_TEST;
+    using CALLOUT_DEVICE_PATH_TEST = _Callout::CALLOUT_DEVICE_PATH_TEST;
+    using metadata_types =
+        std::tuple<CALLOUT_ERRNO_TEST, CALLOUT_DEVICE_PATH_TEST>;
+
+    const char* name() const noexcept
+    {
+        return errName;
+    }
+
+    const char* description() const noexcept
+    {
+        return errDesc;
+    }
+
+    const char* what() const noexcept
+    {
+        return errName;
+    }
+};
+
+} // namespace Device
+} // namespace Example
+} // namespace openbmc_project
+} // namespace xyz
+} // namespace example
+
+namespace xyz
+{
+namespace openbmc_project
+{
+namespace Common
+{
+namespace Callout
+{
+namespace _Device
+{
+
+struct CALLOUT_ERRNO
+{
+    static constexpr auto str = "CALLOUT_ERRNO=%d";
+    static constexpr auto str_short = "CALLOUT_ERRNO";
+    using type = std::tuple<std::decay_t<decltype(str)>, int32_t>;
+    explicit constexpr CALLOUT_ERRNO(int32_t a) : _entry(entry(str, a)){};
+    type _entry;
+};
+struct CALLOUT_DEVICE_PATH
+{
+    static constexpr auto str = "CALLOUT_DEVICE_PATH=%s";
+    static constexpr auto str_short = "CALLOUT_DEVICE_PATH";
+    using type = std::tuple<std::decay_t<decltype(str)>, const char*>;
+    explicit constexpr CALLOUT_DEVICE_PATH(const char* a) :
+        _entry(entry(str, a)){};
+    type _entry;
+};
+
+} // namespace _Device
+
+struct Device
+{
+    static constexpr auto L = level::ERR;
+    using CALLOUT_ERRNO = _Device::CALLOUT_ERRNO;
+    using CALLOUT_DEVICE_PATH = _Device::CALLOUT_DEVICE_PATH;
+    using metadata_types = std::tuple<CALLOUT_ERRNO, CALLOUT_DEVICE_PATH>;
+};
+
+} // namespace Callout
+} // namespace Common
+} // namespace openbmc_project
+} // namespace xyz
+
+namespace details
+{
+
+template <>
+struct map_exception_type<
+    sdbusplus::xyz::openbmc_project::Common::Callout::Error::Device>
+{
+    using type = xyz::openbmc_project::Common::Callout::Device;
+};
+
+} // namespace details
+
+namespace xyz
+{
+namespace openbmc_project
+{
+namespace Common
+{
+namespace Callout
+{
+namespace _GPIO
+{
+
+struct CALLOUT_GPIO_NUM
+{
+    static constexpr auto str = "CALLOUT_GPIO_NUM=%u";
+    static constexpr auto str_short = "CALLOUT_GPIO_NUM";
+    using type = std::tuple<std::decay_t<decltype(str)>, uint32_t>;
+    explicit constexpr CALLOUT_GPIO_NUM(uint32_t a) : _entry(entry(str, a)){};
+    type _entry;
+};
+
+} // namespace _GPIO
+
+struct GPIO
+{
+    static constexpr auto L = level::ERR;
+    using CALLOUT_GPIO_NUM = _GPIO::CALLOUT_GPIO_NUM;
+    using CALLOUT_ERRNO =
+        xyz::openbmc_project::Common::Callout::Device::CALLOUT_ERRNO;
+    using CALLOUT_DEVICE_PATH =
+        xyz::openbmc_project::Common::Callout::Device::CALLOUT_DEVICE_PATH;
+    using metadata_types =
+        std::tuple<CALLOUT_GPIO_NUM, CALLOUT_ERRNO, CALLOUT_DEVICE_PATH>;
+};
+
+} // namespace Callout
+} // namespace Common
+} // namespace openbmc_project
+} // namespace xyz
+
+namespace details
+{
+
+template <>
+struct map_exception_type<
+    sdbusplus::xyz::openbmc_project::Common::Callout::Error::GPIO>
+{
+    using type = xyz::openbmc_project::Common::Callout::GPIO;
+};
+
+} // namespace details
+
+namespace xyz
+{
+namespace openbmc_project
+{
+namespace Common
+{
+namespace Callout
+{
+namespace _IIC
+{
+
+struct CALLOUT_IIC_BUS
+{
+    static constexpr auto str = "CALLOUT_IIC_BUS=%s";
+    static constexpr auto str_short = "CALLOUT_IIC_BUS";
+    using type = std::tuple<std::decay_t<decltype(str)>, const char*>;
+    explicit constexpr CALLOUT_IIC_BUS(const char* a) : _entry(entry(str, a)){};
+    type _entry;
+};
+struct CALLOUT_IIC_ADDR
+{
+    static constexpr auto str = "CALLOUT_IIC_ADDR=0x%hx";
+    static constexpr auto str_short = "CALLOUT_IIC_ADDR";
+    using type = std::tuple<std::decay_t<decltype(str)>, uint16_t>;
+    explicit constexpr CALLOUT_IIC_ADDR(uint16_t a) : _entry(entry(str, a)){};
+    type _entry;
+};
+
+} // namespace _IIC
+
+struct IIC
+{
+    static constexpr auto L = level::ERR;
+    using CALLOUT_IIC_BUS = _IIC::CALLOUT_IIC_BUS;
+    using CALLOUT_IIC_ADDR = _IIC::CALLOUT_IIC_ADDR;
+    using CALLOUT_ERRNO =
+        xyz::openbmc_project::Common::Callout::Device::CALLOUT_ERRNO;
+    using CALLOUT_DEVICE_PATH =
+        xyz::openbmc_project::Common::Callout::Device::CALLOUT_DEVICE_PATH;
+    using metadata_types = std::tuple<CALLOUT_IIC_BUS, CALLOUT_IIC_ADDR,
+                                      CALLOUT_ERRNO, CALLOUT_DEVICE_PATH>;
+};
+
+} // namespace Callout
+} // namespace Common
+} // namespace openbmc_project
+} // namespace xyz
+
+namespace details
+{
+
+template <>
+struct map_exception_type<
+    sdbusplus::xyz::openbmc_project::Common::Callout::Error::IIC>
+{
+    using type = xyz::openbmc_project::Common::Callout::IIC;
+};
+
+} // namespace details
+
+namespace xyz
+{
+namespace openbmc_project
+{
+namespace Common
+{
+namespace Callout
+{
+namespace _Inventory
+{
+
+struct CALLOUT_INVENTORY_PATH
+{
+    static constexpr auto str = "CALLOUT_INVENTORY_PATH=%s";
+    static constexpr auto str_short = "CALLOUT_INVENTORY_PATH";
+    using type = std::tuple<std::decay_t<decltype(str)>, const char*>;
+    explicit constexpr CALLOUT_INVENTORY_PATH(const char* a) :
+        _entry(entry(str, a)){};
+    type _entry;
+};
+
+} // namespace _Inventory
+
+struct Inventory
+{
+    static constexpr auto L = level::ERR;
+    using CALLOUT_INVENTORY_PATH = _Inventory::CALLOUT_INVENTORY_PATH;
+    using metadata_types = std::tuple<CALLOUT_INVENTORY_PATH>;
+};
+
+} // namespace Callout
+} // namespace Common
+} // namespace openbmc_project
+} // namespace xyz
+
+namespace details
+{
+
+template <>
+struct map_exception_type<
+    sdbusplus::xyz::openbmc_project::Common::Callout::Error::Inventory>
+{
+    using type = xyz::openbmc_project::Common::Callout::Inventory;
+};
+
+} // namespace details
+
+namespace xyz
+{
+namespace openbmc_project
+{
+namespace Common
+{
+namespace Callout
+{
+namespace _IPMISensor
+{
+
+struct CALLOUT_IPMI_SENSOR_NUM
+{
+    static constexpr auto str = "CALLOUT_IPMI_SENSOR_NUM=%u";
+    static constexpr auto str_short = "CALLOUT_IPMI_SENSOR_NUM";
+    using type = std::tuple<std::decay_t<decltype(str)>, uint32_t>;
+    explicit constexpr CALLOUT_IPMI_SENSOR_NUM(uint32_t a) :
+        _entry(entry(str, a)){};
+    type _entry;
+};
+
+} // namespace _IPMISensor
+
+struct IPMISensor
+{
+    static constexpr auto L = level::ERR;
+    using CALLOUT_IPMI_SENSOR_NUM = _IPMISensor::CALLOUT_IPMI_SENSOR_NUM;
+    using metadata_types = std::tuple<CALLOUT_IPMI_SENSOR_NUM>;
+};
+
+} // namespace Callout
+} // namespace Common
+} // namespace openbmc_project
+} // namespace xyz
+
+namespace details
+{
+
+template <>
+struct map_exception_type<
+    sdbusplus::xyz::openbmc_project::Common::Callout::Error::IPMISensor>
+{
+    using type = xyz::openbmc_project::Common::Callout::IPMISensor;
+};
+
+} // namespace details
+
+namespace xyz
+{
+namespace openbmc_project
+{
+namespace Common
+{
+namespace Device
+{
+namespace _ReadFailure
+{
+
+} // namespace _ReadFailure
+
+struct ReadFailure
+{
+    static constexpr auto L = level::ERR;
+    using CALLOUT_ERRNO =
+        xyz::openbmc_project::Common::Callout::Device::CALLOUT_ERRNO;
+    using CALLOUT_DEVICE_PATH =
+        xyz::openbmc_project::Common::Callout::Device::CALLOUT_DEVICE_PATH;
+    using metadata_types = std::tuple<CALLOUT_ERRNO, CALLOUT_DEVICE_PATH>;
+};
+
+} // namespace Device
+} // namespace Common
+} // namespace openbmc_project
+} // namespace xyz
+
+namespace details
+{
+
+template <>
+struct map_exception_type<
+    sdbusplus::xyz::openbmc_project::Common::Device::Error::ReadFailure>
+{
+    using type = xyz::openbmc_project::Common::Device::ReadFailure;
+};
+
+} // namespace details
+
+namespace xyz
+{
+namespace openbmc_project
+{
+namespace Common
+{
+namespace Device
+{
+namespace _WriteFailure
+{
+
+} // namespace _WriteFailure
+
+struct WriteFailure
+{
+    static constexpr auto L = level::ERR;
+    using CALLOUT_ERRNO =
+        xyz::openbmc_project::Common::Callout::Device::CALLOUT_ERRNO;
+    using CALLOUT_DEVICE_PATH =
+        xyz::openbmc_project::Common::Callout::Device::CALLOUT_DEVICE_PATH;
+    using metadata_types = std::tuple<CALLOUT_ERRNO, CALLOUT_DEVICE_PATH>;
+};
+
+} // namespace Device
+} // namespace Common
+} // namespace openbmc_project
+} // namespace xyz
+
+namespace details
+{
+
+template <>
+struct map_exception_type<
+    sdbusplus::xyz::openbmc_project::Common::Device::Error::WriteFailure>
+{
+    using type = xyz::openbmc_project::Common::Device::WriteFailure;
+};
+
+} // namespace details
+
+namespace example
+{
+namespace xyz
+{
+namespace openbmc_project
+{
+namespace Example
+{
+namespace Elog
+{
+namespace _TestErrorTwo
+{
+
+struct DEV_ADDR
+{
+    static constexpr auto str = "DEV_ADDR=0x%.8X";
+    static constexpr auto str_short = "DEV_ADDR";
+    using type = std::tuple<std::decay_t<decltype(str)>, uint32_t>;
+    explicit constexpr DEV_ADDR(uint32_t a) : _entry(entry(str, a)){};
+    type _entry;
+};
+struct DEV_ID
+{
+    static constexpr auto str = "DEV_ID=%u";
+    static constexpr auto str_short = "DEV_ID";
+    using type = std::tuple<std::decay_t<decltype(str)>, uint32_t>;
+    explicit constexpr DEV_ID(uint32_t a) : _entry(entry(str, a)){};
+    type _entry;
+};
+struct DEV_NAME
+{
+    static constexpr auto str = "DEV_NAME=%s";
+    static constexpr auto str_short = "DEV_NAME";
+    using type = std::tuple<std::decay_t<decltype(str)>, const char*>;
+    explicit constexpr DEV_NAME(const char* a) : _entry(entry(str, a)){};
+    type _entry;
+};
+
+} // namespace _TestErrorTwo
+
+struct TestErrorTwo : public sdbusplus::exception_t
+{
+    static constexpr auto errName =
+        "example.xyz.openbmc_project.Example.Elog.TestErrorTwo";
+    static constexpr auto errDesc = "This is test error two";
+    static constexpr auto L = level::ERR;
+    using DEV_ADDR = _TestErrorTwo::DEV_ADDR;
+    using DEV_ID = _TestErrorTwo::DEV_ID;
+    using DEV_NAME = _TestErrorTwo::DEV_NAME;
+    using metadata_types = std::tuple<DEV_ADDR, DEV_ID, DEV_NAME>;
+
+    const char* name() const noexcept
+    {
+        return errName;
+    }
+
+    const char* description() const noexcept
+    {
+        return errDesc;
+    }
+
+    const char* what() const noexcept
+    {
+        return errName;
+    }
+};
+
+} // namespace Elog
+} // namespace Example
+} // namespace openbmc_project
+} // namespace xyz
+} // namespace example
+
+namespace example
+{
+namespace xyz
+{
+namespace openbmc_project
+{
+namespace Example
+{
+namespace Elog
+{
+namespace _AutoTestSimple
+{
+
+struct STRING
+{
+    static constexpr auto str = "STRING=%s";
+    static constexpr auto str_short = "STRING";
+    using type = std::tuple<std::decay_t<decltype(str)>, const char*>;
+    explicit constexpr STRING(const char* a) : _entry(entry(str, a)){};
+    type _entry;
+};
+
+} // namespace _AutoTestSimple
+
+struct AutoTestSimple : public sdbusplus::exception_t
+{
+    static constexpr auto errName =
+        "example.xyz.openbmc_project.Example.Elog.AutoTestSimple";
+    static constexpr auto errDesc = "This is a simple test error.";
+    static constexpr auto L = level::ERR;
+    using STRING = _AutoTestSimple::STRING;
+    using metadata_types = std::tuple<STRING>;
+
+    const char* name() const noexcept
+    {
+        return errName;
+    }
+
+    const char* description() const noexcept
+    {
+        return errDesc;
+    }
+
+    const char* what() const noexcept
+    {
+        return errName;
+    }
+};
+
+} // namespace Elog
+} // namespace Example
+} // namespace openbmc_project
+} // namespace xyz
+} // namespace example
+
+namespace example
+{
+namespace xyz
+{
+namespace openbmc_project
+{
+namespace Example
+{
+namespace Elog
+{
+namespace _TestCallout
+{
+
+struct DEV_ADDR
+{
+    static constexpr auto str = "DEV_ADDR=0x%.8X";
+    static constexpr auto str_short = "DEV_ADDR";
+    using type = std::tuple<std::decay_t<decltype(str)>, uint32_t>;
+    explicit constexpr DEV_ADDR(uint32_t a) : _entry(entry(str, a)){};
+    type _entry;
+};
+
+} // namespace _TestCallout
+
+struct TestCallout : public sdbusplus::exception_t
+{
+    static constexpr auto errName =
+        "example.xyz.openbmc_project.Example.Elog.TestCallout";
+    static constexpr auto errDesc = "This is test error TestCallout";
+    static constexpr auto L = level::ERR;
+    using DEV_ADDR = _TestCallout::DEV_ADDR;
+    using CALLOUT_ERRNO_TEST = example::xyz::openbmc_project::Example::Device::
+        Callout::CALLOUT_ERRNO_TEST;
+    using CALLOUT_DEVICE_PATH_TEST = example::xyz::openbmc_project::Example::
+        Device::Callout::CALLOUT_DEVICE_PATH_TEST;
+    using metadata_types =
+        std::tuple<DEV_ADDR, CALLOUT_ERRNO_TEST, CALLOUT_DEVICE_PATH_TEST>;
+
+    const char* name() const noexcept
+    {
+        return errName;
+    }
+
+    const char* description() const noexcept
+    {
+        return errDesc;
+    }
+
+    const char* what() const noexcept
+    {
+        return errName;
+    }
+};
+
+} // namespace Elog
+} // namespace Example
+} // namespace openbmc_project
+} // namespace xyz
+} // namespace example
+
+namespace xyz
+{
+namespace openbmc_project
+{
+namespace State
+{
+namespace Shutdown
+{
+namespace Inventory
+{
+namespace _Fan
+{
+
+} // namespace _Fan
+
+struct Fan
+{
+    static constexpr auto L = level::ERR;
+    using metadata_types = std::tuple<>;
+};
+
+} // namespace Inventory
+} // namespace Shutdown
+} // namespace State
+} // namespace openbmc_project
+} // namespace xyz
+
+namespace details
+{
+
+template <>
+struct map_exception_type<
+    sdbusplus::xyz::openbmc_project::State::Shutdown::Inventory::Error::Fan>
+{
+    using type = xyz::openbmc_project::State::Shutdown::Inventory::Fan;
+};
+
+} // namespace details
+
+namespace xyz
+{
+namespace openbmc_project
+{
+namespace State
+{
+namespace Shutdown
+{
+namespace Power
+{
+namespace _Fault
+{
+
+} // namespace _Fault
+
+struct Fault
+{
+    static constexpr auto L = level::ERR;
+    using metadata_types = std::tuple<>;
+};
+
+} // namespace Power
+} // namespace Shutdown
+} // namespace State
+} // namespace openbmc_project
+} // namespace xyz
+
+namespace details
+{
+
+template <>
+struct map_exception_type<
+    sdbusplus::xyz::openbmc_project::State::Shutdown::Power::Error::Fault>
+{
+    using type = xyz::openbmc_project::State::Shutdown::Power::Fault;
+};
+
+} // namespace details
+
+namespace xyz
+{
+namespace openbmc_project
+{
+namespace Sensor
+{
+namespace Device
+{
+namespace _ReadFailure
+{
+
+} // namespace _ReadFailure
+
+struct ReadFailure
+{
+    static constexpr auto L = level::ERR;
+    using CALLOUT_ERRNO =
+        xyz::openbmc_project::Common::Callout::Device::CALLOUT_ERRNO;
+    using CALLOUT_DEVICE_PATH =
+        xyz::openbmc_project::Common::Callout::Device::CALLOUT_DEVICE_PATH;
+    using metadata_types = std::tuple<CALLOUT_ERRNO, CALLOUT_DEVICE_PATH>;
+};
+
+} // namespace Device
+} // namespace Sensor
+} // namespace openbmc_project
+} // namespace xyz
+
+namespace details
+{
+
+template <>
+struct map_exception_type<
+    sdbusplus::xyz::openbmc_project::Sensor::Device::Error::ReadFailure>
+{
+    using type = xyz::openbmc_project::Sensor::Device::ReadFailure;
+};
+
+} // namespace details
+
+namespace xyz
+{
+namespace openbmc_project
+{
+namespace State
+{
+namespace Host
+{
+namespace _SoftOffTimeout
+{
+
+} // namespace _SoftOffTimeout
+
+struct SoftOffTimeout
+{
+    static constexpr auto L = level::ERR;
+    using TIMEOUT_IN_MSEC =
+        xyz::openbmc_project::Common::Timeout::TIMEOUT_IN_MSEC;
+    using metadata_types = std::tuple<TIMEOUT_IN_MSEC>;
+};
+
+} // namespace Host
+} // namespace State
+} // namespace openbmc_project
+} // namespace xyz
+
+namespace details
+{
+
+template <>
+struct map_exception_type<
+    sdbusplus::xyz::openbmc_project::State::Host::Error::SoftOffTimeout>
+{
+    using type = xyz::openbmc_project::State::Host::SoftOffTimeout;
+};
+
+} // namespace details
+
+namespace xyz
+{
+namespace openbmc_project
+{
+namespace Inventory
+{
+namespace _NotPresent
+{
+
+} // namespace _NotPresent
+
+struct NotPresent
+{
+    static constexpr auto L = level::ERR;
+    using CALLOUT_INVENTORY_PATH = xyz::openbmc_project::Common::Callout::
+        Inventory::CALLOUT_INVENTORY_PATH;
+    using metadata_types = std::tuple<CALLOUT_INVENTORY_PATH>;
+};
+
+} // namespace Inventory
+} // namespace openbmc_project
+} // namespace xyz
+
+namespace details
+{
+
+template <>
+struct map_exception_type<
+    sdbusplus::xyz::openbmc_project::Inventory::Error::NotPresent>
+{
+    using type = xyz::openbmc_project::Inventory::NotPresent;
+};
+
+} // namespace details
+
+namespace xyz
+{
+namespace openbmc_project
+{
+namespace Inventory
+{
+namespace _Nonfunctional
+{
+
+} // namespace _Nonfunctional
+
+struct Nonfunctional
+{
+    static constexpr auto L = level::ERR;
+    using CALLOUT_INVENTORY_PATH = xyz::openbmc_project::Common::Callout::
+        Inventory::CALLOUT_INVENTORY_PATH;
+    using metadata_types = std::tuple<CALLOUT_INVENTORY_PATH>;
+};
+
+} // namespace Inventory
+} // namespace openbmc_project
+} // namespace xyz
+
+namespace details
+{
+
+template <>
+struct map_exception_type<
+    sdbusplus::xyz::openbmc_project::Inventory::Error::Nonfunctional>
+{
+    using type = xyz::openbmc_project::Inventory::Nonfunctional;
+};
+
+} // namespace details
+
+namespace xyz
+{
+namespace openbmc_project
+{
+namespace Control
+{
+namespace Device
+{
+namespace _WriteFailure
+{
+
+} // namespace _WriteFailure
+
+struct WriteFailure
+{
+    static constexpr auto L = level::ERR;
+    using CALLOUT_ERRNO =
+        xyz::openbmc_project::Common::Callout::Device::CALLOUT_ERRNO;
+    using CALLOUT_DEVICE_PATH =
+        xyz::openbmc_project::Common::Callout::Device::CALLOUT_DEVICE_PATH;
+    using metadata_types = std::tuple<CALLOUT_ERRNO, CALLOUT_DEVICE_PATH>;
+};
+
+} // namespace Device
+} // namespace Control
+} // namespace openbmc_project
+} // namespace xyz
+
+namespace details
+{
+
+template <>
+struct map_exception_type<
+    sdbusplus::xyz::openbmc_project::Control::Device::Error::WriteFailure>
+{
+    using type = xyz::openbmc_project::Control::Device::WriteFailure;
+};
+
+} // namespace details
+
+namespace example
+{
+namespace xyz
+{
+namespace openbmc_project
+{
+namespace Example
+{
+namespace Elog
+{
+namespace _TestErrorOne
+{
+
+struct ERRNUM
+{
+    static constexpr auto str = "ERRNUM=0x%.4X";
+    static constexpr auto str_short = "ERRNUM";
+    using type = std::tuple<std::decay_t<decltype(str)>, uint16_t>;
+    explicit constexpr ERRNUM(uint16_t a) : _entry(entry(str, a)){};
+    type _entry;
+};
+struct FILE_PATH
+{
+    static constexpr auto str = "FILE_PATH=%s";
+    static constexpr auto str_short = "FILE_PATH";
+    using type = std::tuple<std::decay_t<decltype(str)>, const char*>;
+    explicit constexpr FILE_PATH(const char* a) : _entry(entry(str, a)){};
+    type _entry;
+};
+struct FILE_NAME
+{
+    static constexpr auto str = "FILE_NAME=%s";
+    static constexpr auto str_short = "FILE_NAME";
+    using type = std::tuple<std::decay_t<decltype(str)>, const char*>;
+    explicit constexpr FILE_NAME(const char* a) : _entry(entry(str, a)){};
+    type _entry;
+};
+
+} // namespace _TestErrorOne
+
+struct TestErrorOne : public sdbusplus::exception_t
+{
+    static constexpr auto errName =
+        "example.xyz.openbmc_project.Example.Elog.TestErrorOne";
+    static constexpr auto errDesc = "this is test error one";
+    static constexpr auto L = level::INFO;
+    using ERRNUM = _TestErrorOne::ERRNUM;
+    using FILE_PATH = _TestErrorOne::FILE_PATH;
+    using FILE_NAME = _TestErrorOne::FILE_NAME;
+    using DEV_ADDR =
+        example::xyz::openbmc_project::Example::Elog::TestErrorTwo::DEV_ADDR;
+    using DEV_ID =
+        example::xyz::openbmc_project::Example::Elog::TestErrorTwo::DEV_ID;
+    using DEV_NAME =
+        example::xyz::openbmc_project::Example::Elog::TestErrorTwo::DEV_NAME;
+    using metadata_types =
+        std::tuple<ERRNUM, FILE_PATH, FILE_NAME, DEV_ADDR, DEV_ID, DEV_NAME>;
+
+    const char* name() const noexcept
+    {
+        return errName;
+    }
+
+    const char* description() const noexcept
+    {
+        return errDesc;
+    }
+
+    const char* what() const noexcept
+    {
+        return errName;
+    }
+};
+
+} // namespace Elog
+} // namespace Example
+} // namespace openbmc_project
+} // namespace xyz
+} // namespace example
+
+namespace example
+{
+namespace xyz
+{
+namespace openbmc_project
+{
+namespace Example
+{
+namespace Foo
+{
+namespace _Foo
+{
+
+struct FOO_DATA
+{
+    static constexpr auto str = "FOO_DATA=%s";
+    static constexpr auto str_short = "FOO_DATA";
+    using type = std::tuple<std::decay_t<decltype(str)>, const char*>;
+    explicit constexpr FOO_DATA(const char* a) : _entry(entry(str, a)){};
+    type _entry;
+};
+
+} // namespace _Foo
+
+struct Foo : public sdbusplus::exception_t
+{
+    static constexpr auto errName =
+        "example.xyz.openbmc_project.Example.Foo.Foo";
+    static constexpr auto errDesc = "this is test error Foo";
+    static constexpr auto L = level::INFO;
+    using FOO_DATA = _Foo::FOO_DATA;
+    using ERRNUM =
+        example::xyz::openbmc_project::Example::Elog::TestErrorOne::ERRNUM;
+    using FILE_PATH =
+        example::xyz::openbmc_project::Example::Elog::TestErrorOne::FILE_PATH;
+    using FILE_NAME =
+        example::xyz::openbmc_project::Example::Elog::TestErrorOne::FILE_NAME;
+    using DEV_ADDR =
+        example::xyz::openbmc_project::Example::Elog::TestErrorTwo::DEV_ADDR;
+    using DEV_ID =
+        example::xyz::openbmc_project::Example::Elog::TestErrorTwo::DEV_ID;
+    using DEV_NAME =
+        example::xyz::openbmc_project::Example::Elog::TestErrorTwo::DEV_NAME;
+    using metadata_types = std::tuple<FOO_DATA, ERRNUM, FILE_PATH, FILE_NAME,
+                                      DEV_ADDR, DEV_ID, DEV_NAME>;
+
+    const char* name() const noexcept
+    {
+        return errName;
+    }
+
+    const char* description() const noexcept
+    {
+        return errDesc;
+    }
+
+    const char* what() const noexcept
+    {
+        return errName;
+    }
+};
+
+} // namespace Foo
+} // namespace Example
+} // namespace openbmc_project
+} // namespace xyz
+} // namespace example
+
+namespace example
+{
+namespace xyz
+{
+namespace openbmc_project
+{
+namespace Example
+{
+namespace Bar
+{
+namespace _Bar
+{
+
+struct BAR_DATA
+{
+    static constexpr auto str = "BAR_DATA=%s";
+    static constexpr auto str_short = "BAR_DATA";
+    using type = std::tuple<std::decay_t<decltype(str)>, const char*>;
+    explicit constexpr BAR_DATA(const char* a) : _entry(entry(str, a)){};
+    type _entry;
+};
+
+} // namespace _Bar
+
+struct Bar : public sdbusplus::exception_t
+{
+    static constexpr auto errName =
+        "example.xyz.openbmc_project.Example.Bar.Bar";
+    static constexpr auto errDesc = "this is test error Bar";
+    static constexpr auto L = level::INFO;
+    using BAR_DATA = _Bar::BAR_DATA;
+    using FOO_DATA = example::xyz::openbmc_project::Example::Foo::Foo::FOO_DATA;
+    using ERRNUM =
+        example::xyz::openbmc_project::Example::Elog::TestErrorOne::ERRNUM;
+    using FILE_PATH =
+        example::xyz::openbmc_project::Example::Elog::TestErrorOne::FILE_PATH;
+    using FILE_NAME =
+        example::xyz::openbmc_project::Example::Elog::TestErrorOne::FILE_NAME;
+    using DEV_ADDR =
+        example::xyz::openbmc_project::Example::Elog::TestErrorTwo::DEV_ADDR;
+    using DEV_ID =
+        example::xyz::openbmc_project::Example::Elog::TestErrorTwo::DEV_ID;
+    using DEV_NAME =
+        example::xyz::openbmc_project::Example::Elog::TestErrorTwo::DEV_NAME;
+    using metadata_types = std::tuple<BAR_DATA, FOO_DATA, ERRNUM, FILE_PATH,
+                                      FILE_NAME, DEV_ADDR, DEV_ID, DEV_NAME>;
+
+    const char* name() const noexcept
+    {
+        return errName;
+    }
+
+    const char* description() const noexcept
+    {
+        return errDesc;
+    }
+
+    const char* what() const noexcept
+    {
+        return errName;
+    }
+};
+
+} // namespace Bar
+} // namespace Example
+} // namespace openbmc_project
+} // namespace xyz
+} // namespace example
+
+} // namespace logging
+
+} // namespace phosphor
diff --git a/non-yocto/xyz/openbmc_project/Common/error.hpp b/non-yocto/xyz/openbmc_project/Common/error.hpp
new file mode 100644
index 0000000..d7c38e2
--- /dev/null
+++ b/non-yocto/xyz/openbmc_project/Common/error.hpp
@@ -0,0 +1,75 @@
+#pragma once
+
+#include <sdbusplus/exception.hpp>
+
+namespace sdbusplus
+{
+namespace xyz
+{
+namespace openbmc_project
+{
+namespace Common
+{
+namespace Error
+{
+
+struct Timeout final : public sdbusplus::exception_t
+{
+    static constexpr auto errName = "xyz.openbmc_project.Common.Error.Timeout";
+    static constexpr auto errDesc = "Operation timed out.";
+    static constexpr auto errWhat =
+        "xyz.openbmc_project.Common.Error.Timeout: Operation timed out.";
+
+    const char* name() const noexcept override;
+    const char* description() const noexcept override;
+    const char* what() const noexcept override;
+};
+
+struct InternalFailure final : public sdbusplus::exception_t
+{
+    static constexpr auto errName =
+        "xyz.openbmc_project.Common.Error.InternalFailure";
+    static constexpr auto errDesc = "The operation failed internally.";
+    static constexpr auto errWhat =
+        "xyz.openbmc_project.Common.Error.InternalFailure: The operation "
+        "failed internally.";
+
+    const char* name() const noexcept override;
+    const char* description() const noexcept override;
+    const char* what() const noexcept override;
+};
+
+struct InvalidArgument final : public sdbusplus::exception_t
+{
+    static constexpr auto errName =
+        "xyz.openbmc_project.Common.Error.InvalidArgument";
+    static constexpr auto errDesc = "Invalid argument was given.";
+    static constexpr auto errWhat =
+        "xyz.openbmc_project.Common.Error.InvalidArgument: Invalid argument "
+        "was given.";
+
+    const char* name() const noexcept override;
+    const char* description() const noexcept override;
+    const char* what() const noexcept override;
+};
+
+struct InsufficientPermission final : public sdbusplus::exception_t
+{
+    static constexpr auto errName =
+        "xyz.openbmc_project.Common.Error.InsufficientPermission";
+    static constexpr auto errDesc =
+        "Insufficient permission to perform operation";
+    static constexpr auto errWhat =
+        "xyz.openbmc_project.Common.Error.InsufficientPermission: Insufficient "
+        "permission to perform operation";
+
+    const char* name() const noexcept override;
+    const char* description() const noexcept override;
+    const char* what() const noexcept override;
+};
+
+} // namespace Error
+} // namespace Common
+} // namespace openbmc_project
+} // namespace xyz
+} // namespace sdbusplus
diff --git a/non-yocto/xyz/openbmc_project/Smbios/MDR_V2/error.hpp b/non-yocto/xyz/openbmc_project/Smbios/MDR_V2/error.hpp
new file mode 100644
index 0000000..e26c13d
--- /dev/null
+++ b/non-yocto/xyz/openbmc_project/Smbios/MDR_V2/error.hpp
@@ -0,0 +1,63 @@
+#pragma once
+
+#include <sdbusplus/exception.hpp>
+
+namespace sdbusplus
+{
+namespace xyz
+{
+namespace openbmc_project
+{
+namespace Smbios
+{
+namespace MDR_V2
+{
+namespace Error
+{
+
+struct InvalidParameter final : public sdbusplus::exception_t
+{
+    static constexpr auto errName =
+        "xyz.openbmc_project.Smbios.MDR_V2.Error.InvalidParameter";
+    static constexpr auto errDesc = "An invalid parameter is attempted.";
+    static constexpr auto errWhat =
+        "xyz.openbmc_project.Smbios.MDR_V2.Error.InvalidParameter: An invalid "
+        "parameter is attempted.";
+
+    const char* name() const noexcept override;
+    const char* description() const noexcept override;
+    const char* what() const noexcept override;
+};
+
+struct UpdateInProgress final : public sdbusplus::exception_t
+{
+    static constexpr auto errName =
+        "xyz.openbmc_project.Smbios.MDR_V2.Error.UpdateInProgress";
+    static constexpr auto errDesc = "Update is in progress.";
+    static constexpr auto errWhat = "xyz.openbmc_project.Smbios.MDR_V2.Error."
+                                    "UpdateInProgress: Update is in progress.";
+
+    const char* name() const noexcept override;
+    const char* description() const noexcept override;
+    const char* what() const noexcept override;
+};
+
+struct InvalidId final : public sdbusplus::exception_t
+{
+    static constexpr auto errName =
+        "xyz.openbmc_project.Smbios.MDR_V2.Error.InvalidId";
+    static constexpr auto errDesc = "An invalid Id is attempted.";
+    static constexpr auto errWhat = "xyz.openbmc_project.Smbios.MDR_V2.Error."
+                                    "InvalidId: An invalid Id is attempted.";
+
+    const char* name() const noexcept override;
+    const char* description() const noexcept override;
+    const char* what() const noexcept override;
+};
+
+} // namespace Error
+} // namespace MDR_V2
+} // namespace Smbios
+} // namespace openbmc_project
+} // namespace xyz
+} // namespace sdbusplus
diff --git a/src/bmccontrolservices.cpp b/src/bmccontrolservices.cpp
new file mode 100644
index 0000000..2bebab5
--- /dev/null
+++ b/src/bmccontrolservices.cpp
@@ -0,0 +1,153 @@
+/*
+// Copyright (c) 2018 Intel Corporation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+
+#include "oemcommands.hpp"
+
+#include <openssl/hmac.h>
+
+#include <ipmid/api.hpp>
+#include <ipmid/utils.hpp>
+#include <phosphor-logging/log.hpp>
+#include <sdbusplus/bus.hpp>
+
+void register_netfn_bmc_control_functions() __attribute__((constructor));
+
+enum ipmi_bmc_control_services_return_codes
+{
+    ipmiCCBmcControlInvalidBitMask = 0xCC,
+    ipmiCCBmcControlPasswdInvalid = 0xCD,
+    ipmiCCBmcControlInvalidChannel = 0xD4,
+};
+
+// TODO: Add other services, once they are supported
+static const std::unordered_map<uint8_t, std::string> bmcServices = {
+    {3, "netipmid"},
+    {5, "web"},
+    {6, "ssh"},
+};
+
+static constexpr const char* objectManagerIntf =
+    "org.freedesktop.DBus.ObjectManager";
+static constexpr const char* serviceConfigBasePath =
+    "/xyz/openbmc_project/control/service";
+static constexpr const char* serviceConfigAttrIntf =
+    "xyz.openbmc_project.Control.Service.Attributes";
+static constexpr const char* serviceStateProperty = "State";
+static std::string disableServiceValue = "disabled";
+
+static ipmi_ret_t disableBmcServices(const std::string& objName)
+{
+    std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus();
+    static std::string serviceCfgMgr{};
+    if (serviceCfgMgr.empty())
+    {
+        try
+        {
+            serviceCfgMgr = ipmi::getService(*dbus, objectManagerIntf,
+                                             serviceConfigBasePath);
+        }
+        catch (const sdbusplus::exception::SdBusError& e)
+        {
+            serviceCfgMgr.clear();
+            phosphor::logging::log<phosphor::logging::level::ERR>(
+                "Error: In fetching disabling service manager name");
+            return IPMI_CC_UNSPECIFIED_ERROR;
+        }
+    }
+    auto path = std::string(serviceConfigBasePath) + "/" + objName;
+    try
+    {
+        ipmi::setDbusProperty(*dbus, serviceCfgMgr, path, serviceConfigAttrIntf,
+                              serviceStateProperty,
+                              ipmi::Value(disableServiceValue));
+        phosphor::logging::log<phosphor::logging::level::INFO>(
+            "Disabling service",
+            phosphor::logging::entry("PATH=%s", path.c_str()),
+            phosphor::logging::entry("MGR_NAME=%s", serviceCfgMgr.c_str()));
+        return IPMI_CC_OK;
+    }
+    catch (const sdbusplus::exception_t&)
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Error: Disabling service",
+            phosphor::logging::entry("PATH=%s", path.c_str()),
+            phosphor::logging::entry("MGR_NAME=%s", serviceCfgMgr.c_str()));
+        return IPMI_CC_UNSPECIFIED_ERROR;
+    }
+}
+
+static constexpr size_t controlPasswdSize = 32;
+
+ipmi::RspType<> bmcIntelControlServices(
+    ipmi::Context::ptr ctx,
+    const std::array<uint8_t, controlPasswdSize>& passwd, uint8_t stdServices,
+    uint8_t oemServices)
+{
+    // Execute this command only in KCS interface
+    if (ctx->channel != interfaceKCS)
+    {
+        return ipmi::response(ipmiCCBmcControlInvalidChannel);
+    }
+
+    static std::string hashData("Intel 0penBMC");
+    static std::vector<uint8_t> hashedValue = {
+        0x89, 0x6A, 0xAB, 0x7D, 0xB0, 0x5A, 0x2D, 0x92, 0x41, 0xAD, 0x92,
+        0xEE, 0xD4, 0x82, 0xDE, 0x62, 0x66, 0x16, 0xC1, 0x08, 0xFD, 0x23,
+        0xC6, 0xD8, 0x75, 0xB3, 0x52, 0x53, 0x31, 0x3C, 0x7F, 0x69};
+    std::vector<uint8_t> hashedOutput(EVP_MAX_MD_SIZE, 0);
+    unsigned int outputLen = 0;
+    HMAC(EVP_sha256(), passwd.data(), passwd.size(),
+         reinterpret_cast<const uint8_t*>(hashData.c_str()), hashData.length(),
+         &hashedOutput[0], &outputLen);
+    hashedOutput.resize(outputLen);
+
+    if (hashedOutput != hashedValue)
+    {
+        return ipmi::response(ipmiCCBmcControlPasswdInvalid);
+    }
+
+    if (stdServices == 0 && oemServices == 0)
+    {
+        return ipmi::response(ipmiCCBmcControlInvalidBitMask);
+    }
+
+    ipmi_ret_t retVal = IPMI_CC_OK;
+    for (size_t bitIndex = 0; bitIndex < 8; ++bitIndex)
+    {
+        if (stdServices & (1 << bitIndex))
+        {
+            auto it = bmcServices.find(bitIndex);
+            if (it == bmcServices.end())
+            {
+                return ipmi::response(ipmiCCBmcControlInvalidBitMask);
+            }
+            retVal = disableBmcServices(it->second);
+            if (retVal != IPMI_CC_OK)
+            {
+                return ipmi::response(retVal);
+            }
+        }
+    }
+    return ipmi::responseSuccess();
+}
+
+void register_netfn_bmc_control_functions()
+{
+    ipmi::registerHandler(ipmi::prioOpenBmcBase, netfnIntcOEMGeneral,
+                          static_cast<ipmi_cmd_t>(
+                              IPMINetFnIntelOemGeneralCmds::BmcControlServices),
+                          ipmi::Privilege::User, bmcIntelControlServices);
+}
diff --git a/src/bridgingcommands.cpp b/src/bridgingcommands.cpp
new file mode 100644
index 0000000..0c727f6
--- /dev/null
+++ b/src/bridgingcommands.cpp
@@ -0,0 +1,514 @@
+/*
+// Copyright (c) 2018 Intel Corporation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+
+#include <ipmid/api.h>
+
+#include <bridgingcommands.hpp>
+#include <cstring>
+#include <phosphor-logging/log.hpp>
+#include <sdbusplus/bus.hpp>
+#include <sdbusplus/bus/match.hpp>
+#include <sdbusplus/message.hpp>
+#include <vector>
+
+static constexpr const char *ipmbBus = "xyz.openbmc_project.Ipmi.Channel.Ipmb";
+static constexpr const char *ipmbObj = "/xyz/openbmc_project/Ipmi/Channel/Ipmb";
+static constexpr const char *ipmbIntf = "org.openbmc.Ipmb";
+
+static Bridging bridging;
+
+/**
+ * @brief utils for checksum
+ */
+static bool ipmbChecksumValidate(uint8_t *data, uint8_t length)
+{
+    if (data == nullptr)
+    {
+        return false;
+    }
+
+    uint8_t checksum = 0;
+
+    for (uint8_t idx = 0; idx < length; idx++)
+    {
+        checksum += data[idx];
+    }
+
+    if (0 == checksum)
+    {
+        return true;
+    }
+
+    return false;
+}
+
+static uint8_t ipmbChecksumCompute(uint8_t *data, uint8_t length)
+{
+    if (data == nullptr)
+    {
+        return 0;
+    }
+
+    uint8_t checksum = 0;
+
+    for (uint8_t idx = 0; idx < length; idx++)
+    {
+        checksum += data[idx];
+    }
+
+    checksum = (~checksum) + 1;
+    return checksum;
+}
+
+static inline bool ipmbConnectionHeaderChecksumValidate(ipmbHeader *ipmbHeader)
+{
+    return ipmbChecksumValidate(reinterpret_cast<uint8_t *>(ipmbHeader),
+                                ipmbConnectionHeaderLength);
+}
+
+static inline bool ipmbDataChecksumValidate(ipmbHeader *ipmbHeader,
+                                            uint8_t length)
+{
+    return ipmbChecksumValidate(
+        (reinterpret_cast<uint8_t *>(ipmbHeader) + ipmbConnectionHeaderLength),
+        (length - ipmbConnectionHeaderLength));
+}
+
+static bool isFrameValid(ipmbHeader *frame, uint8_t length)
+{
+    if ((length < ipmbMinFrameLength) || (length > ipmbMaxFrameLength))
+    {
+        return false;
+    }
+
+    if (false == ipmbConnectionHeaderChecksumValidate(frame))
+    {
+        return false;
+    }
+
+    if (false == ipmbDataChecksumValidate(frame, length))
+    {
+        return false;
+    }
+
+    return true;
+}
+
+IpmbRequest::IpmbRequest(const ipmbHeader *ipmbBuffer, size_t bufferLength)
+{
+    address = ipmbBuffer->Header.Req.address;
+    netFn = ipmbNetFnGet(ipmbBuffer->Header.Req.rsNetFnLUN);
+    rsLun = ipmbLunFromNetFnLunGet(ipmbBuffer->Header.Req.rsNetFnLUN);
+    rqSA = ipmbBuffer->Header.Req.rqSA;
+    seq = ipmbSeqGet(ipmbBuffer->Header.Req.rqSeqLUN);
+    rqLun = ipmbLunFromSeqLunGet(ipmbBuffer->Header.Req.rqSeqLUN);
+    cmd = ipmbBuffer->Header.Req.cmd;
+
+    size_t dataLength =
+        bufferLength - (ipmbConnectionHeaderLength +
+                        ipmbRequestDataHeaderLength + ipmbChecksumSize);
+
+    if (dataLength > 0)
+    {
+        data.insert(data.end(), ipmbBuffer->Header.Req.data,
+                    &ipmbBuffer->Header.Req.data[dataLength]);
+    }
+}
+
+IpmbResponse::IpmbResponse(uint8_t address, uint8_t netFn, uint8_t rqLun,
+                           uint8_t rsSA, uint8_t seq, uint8_t rsLun,
+                           uint8_t cmd, uint8_t completionCode,
+                           std::vector<uint8_t> &inputData) :
+    address(address),
+    netFn(netFn), rqLun(rqLun), rsSA(rsSA), seq(seq), rsLun(rsLun), cmd(cmd),
+    completionCode(completionCode)
+{
+    data.reserve(ipmbMaxDataSize);
+
+    if (inputData.size() > 0)
+    {
+        data = std::move(inputData);
+    }
+}
+
+void IpmbResponse::ipmbToi2cConstruct(uint8_t *buffer, size_t *bufferLength)
+{
+    ipmbHeader *ipmbBuffer = (ipmbHeader *)buffer;
+
+    ipmbBuffer->Header.Resp.address = address;
+    ipmbBuffer->Header.Resp.rqNetFnLUN = ipmbNetFnLunSet(netFn, rqLun);
+    ipmbBuffer->Header.Resp.rsSA = rsSA;
+    ipmbBuffer->Header.Resp.rsSeqLUN = ipmbSeqLunSet(seq, rsLun);
+    ipmbBuffer->Header.Resp.cmd = cmd;
+    ipmbBuffer->Header.Resp.completionCode = completionCode;
+
+    ipmbBuffer->Header.Resp.checksum1 = ipmbChecksumCompute(
+        buffer, ipmbConnectionHeaderLength - ipmbChecksumSize);
+
+    if (data.size() > 0)
+    {
+        std::copy(
+            data.begin(), data.end(),
+            &buffer[ipmbConnectionHeaderLength + ipmbResponseDataHeaderLength]);
+    }
+
+    *bufferLength = data.size() + ipmbResponseDataHeaderLength +
+                    ipmbConnectionHeaderLength + ipmbChecksumSize;
+
+    buffer[*bufferLength - ipmbChecksumSize] =
+        ipmbChecksumCompute(&buffer[ipmbChecksum2StartOffset],
+                            (ipmbResponseDataHeaderLength + data.size()));
+}
+
+void IpmbRequest::prepareRequest(sdbusplus::message::message &mesg)
+{
+    mesg.append(ipmbMeChannelNum, netFn, rqLun, cmd, data);
+}
+
+Bridging::Bridging() : dbus(ipmid_get_sd_bus_connection())
+{
+}
+
+ipmi_return_codes Bridging::handleIpmbChannel(sSendMessageReq *sendMsgReq,
+                                              ipmi_response_t response,
+                                              ipmi_data_len_t dataLen)
+{
+    if ((*dataLen < (sizeof(sSendMessageReq) + ipmbMinFrameLength)) ||
+        (*dataLen > (sizeof(sSendMessageReq) + ipmbMaxFrameLength)))
+    {
+        *dataLen = 0;
+        return IPMI_CC_REQ_DATA_LEN_INVALID;
+    }
+
+    auto sendMsgReqData = reinterpret_cast<ipmbHeader *>(sendMsgReq->data);
+
+    // TODO: check privilege lvl. Bridging to ME requires Administrator lvl
+
+    // allow bridging to ME only
+    if (sendMsgReqData->Header.Req.address != ipmbMeSlaveAddress)
+    {
+        phosphor::logging::log<phosphor::logging::level::INFO>(
+            "handleIpmbChannel, IPMB address invalid");
+        *dataLen = 0;
+        return IPMI_CC_PARM_OUT_OF_RANGE;
+    }
+
+    // check allowed modes
+    if (sendMsgReq->modeGet() != modeNoTracking &&
+        sendMsgReq->modeGet() != modeTrackRequest)
+    {
+        phosphor::logging::log<phosphor::logging::level::INFO>(
+            "handleIpmbChannel, mode not supported");
+        *dataLen = 0;
+        return IPMI_CC_PARM_OUT_OF_RANGE;
+    }
+
+    // check if request contains valid IPMB frame
+    if (!isFrameValid(sendMsgReqData, (*dataLen - sizeof(sSendMessageReq))))
+    {
+        phosphor::logging::log<phosphor::logging::level::INFO>(
+            "handleIpmbChannel, IPMB frame invalid");
+        *dataLen = 0;
+        return IPMI_CC_PARM_OUT_OF_RANGE;
+    }
+
+    auto ipmbRequest =
+        IpmbRequest(sendMsgReqData, (*dataLen - sizeof(sSendMessageReq)));
+
+    std::tuple<int, uint8_t, uint8_t, uint8_t, uint8_t, std::vector<uint8_t>>
+        ipmbResponse;
+
+    // send request to IPMB
+    try
+    {
+        auto mesg =
+            dbus.new_method_call(ipmbBus, ipmbObj, ipmbIntf, "sendRequest");
+        ipmbRequest.prepareRequest(mesg);
+        auto ret = dbus.call(mesg);
+        ret.read(ipmbResponse);
+    }
+    catch (sdbusplus::exception::SdBusError &e)
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "handleIpmbChannel, dbus call exception");
+        *dataLen = 0;
+        return IPMI_CC_UNSPECIFIED_ERROR;
+    }
+
+    std::vector<uint8_t> dataReceived(0);
+    int status = -1;
+    uint8_t netFn = 0, lun = 0, cmd = 0, cc = 0;
+
+    std::tie(status, netFn, lun, cmd, cc, dataReceived) = ipmbResponse;
+
+    auto respReceived =
+        IpmbResponse(ipmbRequest.rqSA, netFn, lun, ipmbRequest.address,
+                     ipmbRequest.seq, lun, cmd, cc, dataReceived);
+
+    // check IPMB layer status
+    if (status)
+    {
+        phosphor::logging::log<phosphor::logging::level::WARNING>(
+            "handleIpmbChannel, ipmb returned non zero status");
+        *dataLen = 0;
+        return IPMI_CC_RESPONSE_ERROR;
+    }
+
+    auto sendMsgRes = reinterpret_cast<uint8_t *>(response);
+
+    switch (sendMsgReq->modeGet())
+    {
+        case modeNoTracking:
+            if (responseQueue.size() == responseQueueMaxSize)
+            {
+                *dataLen = 0;
+                return IPMI_CC_BUSY;
+            }
+            responseQueue.insert(responseQueue.end(), std::move(respReceived));
+            *dataLen = 0;
+            return IPMI_CC_OK;
+
+            break;
+        case modeTrackRequest:
+            respReceived.ipmbToi2cConstruct(sendMsgRes, dataLen);
+            return IPMI_CC_OK;
+
+            break;
+        default:
+            phosphor::logging::log<phosphor::logging::level::INFO>(
+                "handleIpmbChannel, mode not supported");
+            *dataLen = 0;
+            return IPMI_CC_PARM_OUT_OF_RANGE;
+    }
+
+    *dataLen = 0;
+    return IPMI_CC_UNSPECIFIED_ERROR;
+}
+
+ipmi_return_codes Bridging::sendMessageHandler(ipmi_request_t request,
+                                               ipmi_response_t response,
+                                               ipmi_data_len_t dataLen)
+{
+    ipmi_return_codes retCode = IPMI_CC_OK;
+
+    if (*dataLen < sizeof(sSendMessageReq))
+    {
+        *dataLen = 0;
+        return IPMI_CC_REQ_DATA_LEN_INVALID;
+    }
+
+    auto sendMsgReq = reinterpret_cast<sSendMessageReq *>(request);
+
+    // check message fields:
+    // encryption not supported
+    if (sendMsgReq->encryptionGet() != 0)
+    {
+        phosphor::logging::log<phosphor::logging::level::INFO>(
+            "sendMessageHandler, encryption not supported");
+        *dataLen = 0;
+        return IPMI_CC_PARM_OUT_OF_RANGE;
+    }
+
+    // authentication not supported
+    if (sendMsgReq->authenticationGet() != 0)
+    {
+        phosphor::logging::log<phosphor::logging::level::INFO>(
+            "sendMessageHandler, authentication not supported");
+        *dataLen = 0;
+        return IPMI_CC_PARM_OUT_OF_RANGE;
+    }
+
+    switch (sendMsgReq->channelNumGet())
+    {
+        // we only handle ipmb for now
+        case targetChannelIpmb:
+        case targetChannelOtherLan:
+            retCode = handleIpmbChannel(sendMsgReq, response, dataLen);
+            break;
+        // fall through to default
+        case targetChannelIcmb10:
+        case targetChannelIcmb09:
+        case targetChannelLan:
+        case targetChannelSerialModem:
+        case targetChannelPciSmbus:
+        case targetChannelSmbus10:
+        case targetChannelSmbus20:
+        case targetChannelSystemInterface:
+        default:
+            phosphor::logging::log<phosphor::logging::level::INFO>(
+                "sendMessageHandler, TargetChannel invalid");
+            *dataLen = 0;
+            return IPMI_CC_PARM_OUT_OF_RANGE;
+    }
+
+    return retCode;
+}
+
+ipmi_return_codes Bridging::getMessageHandler(ipmi_request_t request,
+                                              ipmi_response_t response,
+                                              ipmi_data_len_t dataLen)
+{
+    if (*dataLen != 0)
+    {
+        *dataLen = 0;
+        return IPMI_CC_REQ_DATA_LEN_INVALID;
+    }
+
+    auto getMsgRes = reinterpret_cast<sGetMessageRes *>(response);
+    auto getMsgResData = static_cast<uint8_t *>(getMsgRes->data);
+
+    std::memset(getMsgRes, 0, sizeof(sGetMessageRes));
+
+    auto respQueueItem = responseQueue.begin();
+
+    if (respQueueItem == responseQueue.end())
+    {
+        phosphor::logging::log<phosphor::logging::level::INFO>(
+            "getMessageHandler, no data available");
+        *dataLen = 0;
+        return ipmiGetMessageCmdDataNotAvailable;
+    }
+
+    // set message fields
+    getMsgRes->privilegeLvlSet(SYSTEM_INTERFACE);
+    getMsgRes->channelNumSet(targetChannelSystemInterface);
+
+    // construct response
+    respQueueItem->ipmbToi2cConstruct(getMsgResData, dataLen);
+    responseQueue.erase(respQueueItem);
+
+    *dataLen = *dataLen + sizeof(sGetMessageRes);
+    return IPMI_CC_OK;
+}
+
+ipmi_return_codes Bridging::getMessageFlagsHandler(ipmi_request_t request,
+                                                   ipmi_response_t response,
+                                                   ipmi_data_len_t dataLen)
+{
+    if (*dataLen != 0)
+    {
+        *dataLen = 0;
+        return IPMI_CC_REQ_DATA_LEN_INVALID;
+    }
+
+    auto getMsgFlagsRes = reinterpret_cast<sGetMessageFlagsResp *>(response);
+
+    std::memset(getMsgFlagsRes, 0, sizeof(sGetMessageFlagsResp));
+
+    // preserve current (legacy) behaviour
+    getMsgFlagsRes->eventMessageBitSet(1);
+
+    // set message fields
+    if (responseQueue.size() > 0)
+    {
+        getMsgFlagsRes->receiveMessageBitSet(1);
+    }
+    else
+    {
+        getMsgFlagsRes->receiveMessageBitSet(0);
+    }
+
+    *dataLen = sizeof(sGetMessageFlagsResp);
+
+    return IPMI_CC_OK;
+}
+
+ipmi_return_codes Bridging::clearMessageFlagsHandler(ipmi_request_t request,
+                                                     ipmi_response_t response,
+                                                     ipmi_data_len_t dataLen)
+{
+    if (*dataLen != sizeof(sClearMessageFlagsReq))
+    {
+        return IPMI_CC_REQ_DATA_LEN_INVALID;
+    }
+
+    auto clearMsgFlagsReq = reinterpret_cast<sClearMessageFlagsReq *>(request);
+
+    if (clearMsgFlagsReq->receiveMessageBitGet() == 1)
+    {
+        responseQueue.clear();
+    }
+
+    return IPMI_CC_OK;
+}
+
+ipmi_ret_t ipmiAppSendMessage(ipmi_netfn_t netFn, ipmi_cmd_t cmd,
+                              ipmi_request_t request, ipmi_response_t response,
+                              ipmi_data_len_t dataLen, ipmi_context_t context)
+{
+    ipmi_ret_t retCode = IPMI_CC_OK;
+    retCode = bridging.sendMessageHandler(request, response, dataLen);
+
+    return retCode;
+}
+
+ipmi_ret_t ipmiAppGetMessage(ipmi_netfn_t netFn, ipmi_cmd_t cmd,
+                             ipmi_request_t request, ipmi_response_t response,
+                             ipmi_data_len_t dataLen, ipmi_context_t context)
+{
+    ipmi_ret_t retCode = IPMI_CC_OK;
+    retCode = bridging.getMessageHandler(request, response, dataLen);
+
+    return retCode;
+}
+
+ipmi_ret_t ipmiAppGetMessageFlags(ipmi_netfn_t netFn, ipmi_cmd_t cmd,
+                                  ipmi_request_t request,
+                                  ipmi_response_t response,
+                                  ipmi_data_len_t dataLen,
+                                  ipmi_context_t context)
+{
+    ipmi_ret_t retCode = IPMI_CC_OK;
+    retCode = bridging.getMessageFlagsHandler(request, response, dataLen);
+
+    return retCode;
+}
+
+ipmi_ret_t ipmiAppClearMessageFlags(ipmi_netfn_t netFn, ipmi_cmd_t cmd,
+                                    ipmi_request_t request,
+                                    ipmi_response_t response,
+                                    ipmi_data_len_t dataLen,
+                                    ipmi_context_t context)
+{
+    ipmi_ret_t retCode = IPMI_CC_OK;
+    retCode = bridging.clearMessageFlagsHandler(request, response, dataLen);
+
+    *dataLen = 0;
+
+    return retCode;
+}
+
+static void register_bridging_functions() __attribute__((constructor));
+static void register_bridging_functions()
+{
+    ipmi_register_callback(
+        NETFUN_APP, Bridging::IpmiAppBridgingCmds::ipmiCmdClearMessageFlags,
+        NULL, ipmiAppClearMessageFlags, PRIVILEGE_USER);
+
+    ipmi_register_callback(
+        NETFUN_APP, Bridging::IpmiAppBridgingCmds::ipmiCmdGetMessageFlags, NULL,
+        ipmiAppGetMessageFlags, PRIVILEGE_USER);
+
+    ipmi_register_callback(NETFUN_APP,
+                           Bridging::IpmiAppBridgingCmds::ipmiCmdGetMessage,
+                           NULL, ipmiAppGetMessage, PRIVILEGE_USER);
+
+    ipmi_register_callback(NETFUN_APP,
+                           Bridging::IpmiAppBridgingCmds::ipmiCmdSendMessage,
+                           NULL, ipmiAppSendMessage, PRIVILEGE_USER);
+
+    return;
+}
diff --git a/src/manufacturingcommands.cpp b/src/manufacturingcommands.cpp
new file mode 100644
index 0000000..7bbb970
--- /dev/null
+++ b/src/manufacturingcommands.cpp
@@ -0,0 +1,628 @@
+/*
+// Copyright (c) 2018 Intel Corporation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+
+#include <boost/process/child.hpp>
+#include <ipmid/api.hpp>
+#include <manufacturingcommands.hpp>
+#include <oemcommands.hpp>
+
+namespace ipmi
+{
+
+Manufacturing mtm;
+
+static auto revertTimeOut =
+    std::chrono::duration_cast<std::chrono::microseconds>(
+        std::chrono::seconds(60)); // 1 minute timeout
+
+static constexpr const char* idButtonPath =
+    "/xyz/openbmc_project/Chassis/Buttons/ID0";
+static constexpr const char* idButtonInterface =
+    "xyz.openbmc_project.Chassis.Buttons.ID";
+static constexpr const char* idButtonMemberPressed = "Pressed";
+
+static constexpr const char* callbackMgrService =
+    "xyz.openbmc_project.CallbackManager";
+static constexpr const char* callbackMgrIntf =
+    "xyz.openbmc_project.CallbackManager";
+static constexpr const char* callbackMgrObjPath =
+    "/xyz/openbmc_project/CallbackManager";
+static constexpr const char* retriggerLedUpdate = "RetriggerLEDUpdate";
+
+const static constexpr char* systemDService = "org.freedesktop.systemd1";
+const static constexpr char* systemDObjPath = "/org/freedesktop/systemd1";
+const static constexpr char* systemDMgrIntf =
+    "org.freedesktop.systemd1.Manager";
+const static constexpr char* pidControlService = "phosphor-pid-control.service";
+
+// TODO: Temporary place to test the working code. Will be moved to
+// gpio daemon
+constexpr const char* passthroughPath = "/usr/bin/set-passthrough.sh";
+void disablePassthrough(bool value)
+{
+    boost::process::child c(passthroughPath, value ? "0" : "1");
+    c.wait();
+}
+
+ipmi_ret_t ledStoreAndSet(SmSignalSet signal, std::string setState)
+{
+    LedProperty* ledProp = mtm.findLedProperty(signal);
+    if (ledProp == nullptr)
+    {
+        return IPMI_CC_INVALID_FIELD_REQUEST;
+    }
+
+    std::string ledName = ledProp->getName();
+    std::string ledService = ledServicePrefix + ledName;
+    std::string ledPath = ledPathPrefix + ledName;
+    ipmi::Value presentState;
+
+    if (false == ledProp->getLock())
+    {
+        if (mtm.getProperty(ledService.c_str(), ledPath.c_str(), ledIntf,
+                            "State", &presentState) != 0)
+        {
+            return IPMI_CC_UNSPECIFIED_ERROR;
+        }
+        ledProp->setPrevState(std::get<std::string>(presentState));
+        ledProp->setLock(true);
+        if (signal == SmSignalSet::smPowerFaultLed ||
+            signal == SmSignalSet::smSystemReadyLed)
+        {
+            mtm.revertLedCallback = true;
+        }
+    }
+    if (mtm.setProperty(ledService.c_str(), ledPath.c_str(), ledIntf, "State",
+                        ledStateStr + setState) != 0)
+    {
+        return IPMI_CC_UNSPECIFIED_ERROR;
+    }
+    return IPMI_CC_OK;
+}
+
+ipmi_ret_t ledRevert(SmSignalSet signal)
+{
+    LedProperty* ledProp = mtm.findLedProperty(signal);
+    if (ledProp == nullptr)
+    {
+        return IPMI_CC_INVALID_FIELD_REQUEST;
+    }
+    if (true == ledProp->getLock())
+    {
+        ledProp->setLock(false);
+        if (signal == SmSignalSet::smPowerFaultLed ||
+            signal == SmSignalSet::smSystemReadyLed)
+        {
+            try
+            {
+                ipmi::method_no_args::callDbusMethod(
+                    *getSdBus(), callbackMgrService, callbackMgrObjPath,
+                    callbackMgrIntf, retriggerLedUpdate);
+            }
+            catch (sdbusplus::exception_t& e)
+            {
+                return IPMI_CC_UNSPECIFIED_ERROR;
+            }
+            mtm.revertLedCallback = false;
+        }
+        else
+        {
+            std::string ledName = ledProp->getName();
+            std::string ledService = ledServicePrefix + ledName;
+            std::string ledPath = ledPathPrefix + ledName;
+            if (mtm.setProperty(ledService.c_str(), ledPath.c_str(), ledIntf,
+                                "State", ledProp->getPrevState()) != 0)
+            {
+                return IPMI_CC_UNSPECIFIED_ERROR;
+            }
+        }
+    }
+    return IPMI_CC_OK;
+}
+
+void Manufacturing::initData()
+{
+    gpioPaths[(uint8_t)SmSignalGet::smPowerButton] = "Power_Button";
+    gpioPaths[(uint8_t)SmSignalGet::smResetButton] = "Reset_Button";
+    gpioPaths[(uint8_t)SmSignalGet::smIdentifyButton] = "ID_Button";
+    gpioPaths[(uint8_t)SmSignalGet::smFpLcpEnterButton] = "Lcp_Enter_Button";
+    gpioPaths[(uint8_t)SmSignalGet::smFpLcpLeftButton] = "Lcp_Left_Button";
+    gpioPaths[(uint8_t)SmSignalGet::smFpLcpRightButton] = "Lcp_Right_Button";
+    gpioPaths[(uint8_t)SmSignalGet::smNmiButton] = "Nmi_Button";
+
+    ledPropertyList.push_back(
+        LedProperty(SmSignalSet::smPowerFaultLed, "status_amber"));
+    ledPropertyList.push_back(
+        LedProperty(SmSignalSet::smSystemReadyLed, "status_green"));
+    ledPropertyList.push_back(
+        LedProperty(SmSignalSet::smIdentifyLed, "identify"));
+}
+
+void Manufacturing::revertTimerHandler()
+{
+    for (const auto& signal : revertSmSignalGetVector)
+    {
+        mtm.setProperty(gpioService,
+                        mtm.getGpioPathForSmSignal((uint8_t)signal), gpioIntf,
+                        "Ignore", false);
+    }
+    revertSmSignalGetVector.clear();
+    disablePassthrough(false);
+    if (revertFanPWM)
+    {
+        revertFanPWM = false;
+        disablePidControlService(false);
+    }
+
+    for (const auto& ledProperty : ledPropertyList)
+    {
+        const std::string& ledName = ledProperty.getName();
+        ledRevert(ledProperty.getSignal());
+    }
+}
+
+Manufacturing::Manufacturing() :
+    revertTimer([&](void) { revertTimerHandler(); })
+{
+    initData();
+}
+
+int8_t Manufacturing::getProperty(const char* service, std::string path,
+                                  const char* interface,
+                                  std::string propertyName, ipmi::Value* reply)
+{
+    try
+    {
+        *reply = ipmi::getDbusProperty(*getSdBus(), service, path.c_str(),
+                                       interface, propertyName);
+    }
+    catch (const sdbusplus::exception::SdBusError& e)
+    {
+        phosphor::logging::log<phosphor::logging::level::INFO>(
+            "ERROR: getProperty");
+        return -1;
+    }
+
+    return 0;
+}
+
+int8_t Manufacturing::setProperty(const char* service, std::string path,
+                                  const char* interface,
+                                  std::string propertyName, ipmi::Value value)
+{
+    try
+    {
+        ipmi::setDbusProperty(*getSdBus(), service, path.c_str(), interface,
+                              propertyName, value);
+    }
+    catch (const sdbusplus::exception::SdBusError& e)
+    {
+        phosphor::logging::log<phosphor::logging::level::INFO>(
+            "ERROR: setProperty");
+        return -1;
+    }
+
+    return 0;
+}
+
+int8_t Manufacturing::disablePidControlService(const bool disable)
+{
+    try
+    {
+        auto dbus = getSdBus();
+        auto method = dbus->new_method_call(systemDService, systemDObjPath,
+                                            systemDMgrIntf,
+                                            disable ? "StopUnit" : "StartUnit");
+        method.append(pidControlService, "replace");
+        auto reply = dbus->call(method);
+    }
+    catch (const sdbusplus::exception::SdBusError& e)
+    {
+        phosphor::logging::log<phosphor::logging::level::INFO>(
+            "ERROR: phosphor-pid-control service start or stop failed");
+        return -1;
+    }
+    return 0;
+}
+
+std::tuple<uint8_t, ipmi_ret_t, uint8_t>
+    Manufacturing::proccessSignal(SmSignalGet signal, SmActionGet action)
+{
+    int8_t ret = 0;
+    uint8_t retCode = 0;
+    uint8_t dataLen = 0;
+    uint8_t value = 0;
+    ipmi::Value reply;
+
+    switch (action)
+    {
+        case SmActionGet::sample:
+            phosphor::logging::log<phosphor::logging::level::INFO>(
+                "case SmActionGet::sample");
+            break;
+        case SmActionGet::ignore:
+        {
+            phosphor::logging::log<phosphor::logging::level::INFO>(
+                "case SmActionGet::ignore");
+            if (std::find(revertSmSignalGetVector.begin(),
+                          revertSmSignalGetVector.end(),
+                          signal) == revertSmSignalGetVector.end())
+            {
+                // Todo: Needs to be replaced with pass-through of particular
+                // pin
+                disablePassthrough(true);
+                ret = mtm.setProperty(
+                    gpioService, mtm.getGpioPathForSmSignal((uint8_t)signal),
+                    gpioIntf, "Ignore", true);
+                if (ret < 0)
+                {
+                    dataLen = 0;
+                    retCode = IPMI_CC_INVALID_FIELD_REQUEST;
+                }
+                revertSmSignalGetVector.push_back(signal);
+                revertTimer.start(revertTimeOut);
+            }
+        }
+        break;
+        case SmActionGet::revert:
+        {
+            phosphor::logging::log<phosphor::logging::level::INFO>(
+                "case SmActionGet::revert");
+            auto iter = std::find(revertSmSignalGetVector.begin(),
+                                  revertSmSignalGetVector.end(), signal);
+            if (iter != revertSmSignalGetVector.end())
+            {
+                ret = mtm.setProperty(
+                    gpioService, mtm.getGpioPathForSmSignal((uint8_t)signal),
+                    gpioIntf, "Ignore", false);
+                if (ret < 0)
+                {
+                    dataLen = 0;
+                    retCode = IPMI_CC_INVALID_FIELD_REQUEST;
+                }
+                revertSmSignalGetVector.erase(iter);
+                // Todo: Needs to be replaced with pass-through of particular
+                // pin
+                disablePassthrough(true);
+                if (revertSmSignalGetVector.size() == 0)
+                {
+                    revertTimer.stop();
+                }
+            }
+        }
+        break;
+
+        default:
+            dataLen = 0;
+            retCode = IPMI_CC_INVALID_FIELD_REQUEST;
+            break;
+    }
+
+    if (ret == 0) // No error happend, cmd will return with gpio value
+    {
+        ret = mtm.getProperty(gpioService,
+                              mtm.getGpioPathForSmSignal((uint8_t)signal),
+                              gpioIntf, "SampledValue", &reply);
+        if (ret < 0)
+        {
+            dataLen = 0;
+            retCode = IPMI_CC_INVALID_FIELD_REQUEST;
+        }
+        else
+        {
+            dataLen = 1;
+            value = std::get<bool>(reply);
+        }
+    }
+
+    return std::make_tuple(dataLen, retCode, value);
+}
+
+ipmi_ret_t ipmi_app_mtm_get_signal(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+                                   ipmi_request_t request,
+                                   ipmi_response_t response,
+                                   ipmi_data_len_t data_len,
+                                   ipmi_context_t context)
+{
+    ipmi_ret_t retCode = IPMI_CC_OK;
+    int8_t ret = 0;
+    GetSmSignalReq* pReq = NULL;
+    GetSmSignalRsp* pRsp = NULL;
+
+    pReq = static_cast<GetSmSignalReq*>(request);
+    pRsp = static_cast<GetSmSignalRsp*>(response);
+
+    ipmi::Value reply;
+
+    if ((*data_len == sizeof(*pReq)) &&
+        (mtm.getAccessLvl() >= MtmLvl::mtmAvailable))
+    {
+        switch (pReq->Signal)
+        {
+            case SmSignalGet::smFanPwmGet:
+            {
+                std::string fullPath =
+                    fanPwmPath + std::to_string(pReq->Instance);
+                ret = mtm.getProperty(fanService, fullPath, fanIntf, "Value",
+                                      &reply);
+                if (ret < 0)
+                {
+                    *data_len = 0;
+                    retCode = IPMI_CC_INVALID_FIELD_REQUEST;
+                    break;
+                }
+                *data_len = 1;
+                pRsp->SigVal = std::get<double>(reply);
+            }
+            break;
+            case SmSignalGet::smFanTachometerGet:
+            {
+                // Full path calculation pattern:
+                // Instance 1 path is
+                // /xyz/openbmc_project/sensors/fan_tach/Fan_1a Instance 2 path
+                // is /xyz/openbmc_project/sensors/fan_tach/Fan_1b Instance 3
+                // path is /xyz/openbmc_project/sensors/fan_tach/Fan_2a
+                // and so on...
+                std::string fullPath = fanTachPathPrefix;
+                std::string fanAb = (pReq->Instance % 2) == 0 ? "b" : "a";
+                if (0 == pReq->Instance)
+                {
+                    *data_len = 0;
+                    retCode = IPMI_CC_INVALID_FIELD_REQUEST;
+                    break;
+                }
+                else if (0 == pReq->Instance / 2)
+                {
+                    fullPath += std::string("1") + fanAb;
+                }
+                else
+                {
+                    fullPath += std::to_string(pReq->Instance / 2) + fanAb;
+                }
+
+                ret = mtm.getProperty(fanService, fullPath, fanIntf, "Value",
+                                      &reply);
+                if (ret < 0)
+                {
+                    *data_len = 0;
+                    retCode = IPMI_CC_INVALID_FIELD_REQUEST;
+                    break;
+                }
+
+                uint16_t value = std::get<double>(reply);
+                *data_len = sizeof(*pRsp);
+
+                pRsp->SigVal = FAN_PRESENT | FAN_SENSOR_PRESENT;
+                pRsp->SigVal1 = value & 0x00FF;
+                pRsp->SigVal2 = (value >> 8) & 0xFF;
+            }
+            break;
+            case SmSignalGet::smResetButton:      // gpio32
+            case SmSignalGet::smPowerButton:      // gpio34
+            case SmSignalGet::smFpLcpEnterButton: // gpio51
+            case SmSignalGet::smFpLcpLeftButton:  // gpio52
+            case SmSignalGet::smFpLcpRightButton: // gpio53
+            case SmSignalGet::smNmiButton:        // gpio217
+            case SmSignalGet::smIdentifyButton:   // gpio218
+                std::tie(*data_len, retCode, pRsp->SigVal) =
+                    mtm.proccessSignal(pReq->Signal, pReq->Action);
+                *data_len = sizeof(pRsp->SigVal);
+                break;
+            default:
+                *data_len = 0;
+                retCode = IPMI_CC_INVALID_FIELD_REQUEST;
+                break;
+        }
+    }
+    else
+    {
+        *data_len = 0;
+        retCode = IPMI_CC_REQ_DATA_LEN_INVALID;
+    }
+
+    return retCode;
+}
+
+ipmi_ret_t ipmi_app_mtm_set_signal(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+                                   ipmi_request_t request,
+                                   ipmi_response_t response,
+                                   ipmi_data_len_t data_len,
+                                   ipmi_context_t context)
+{
+    uint8_t ret = 0;
+    ipmi_ret_t retCode = IPMI_CC_OK;
+    SetSmSignalReq* pReq = static_cast<SetSmSignalReq*>(request);
+    std::string ledName;
+    ///////////////////  Signal to led configuration ////////////////
+    //        {SM_SYSTEM_READY_LED, STAT_GRN_LED},    GPIOS4  gpio148
+    //        {SM_POWER_FAULT_LED, STAT_AMB_LED},     GPIOS5  gpio149
+    //        {SM_IDENTIFY_LED, IDENTIFY_LED},        GPIOS6  gpio150
+    //        {SM_SPEAKER, SPEAKER},                  GPIOAB0 gpio216
+    /////////////////////////////////////////////////////////////////
+    if ((*data_len == sizeof(*pReq)) &&
+        (mtm.getAccessLvl() >= MtmLvl::mtmAvailable))
+    {
+        switch (pReq->Signal)
+        {
+            case SmSignalSet::smPowerFaultLed:
+            case SmSignalSet::smSystemReadyLed:
+            case SmSignalSet::smIdentifyLed:
+                switch (pReq->Action)
+                {
+                    case SmActionSet::forceDeasserted:
+                    {
+                        phosphor::logging::log<phosphor::logging::level::INFO>(
+                            "case SmActionSet::forceDeasserted");
+
+                        retCode =
+                            ledStoreAndSet(pReq->Signal, std::string("Off"));
+                        if (retCode != IPMI_CC_OK)
+                        {
+                            break;
+                        }
+                        mtm.revertTimer.start(revertTimeOut);
+                    }
+                    break;
+                    case SmActionSet::forceAsserted:
+                    {
+                        phosphor::logging::log<phosphor::logging::level::INFO>(
+                            "case SmActionSet::forceAsserted");
+
+                        retCode =
+                            ledStoreAndSet(pReq->Signal, std::string("On"));
+                        if (retCode != IPMI_CC_OK)
+                        {
+                            break;
+                        }
+                        mtm.revertTimer.start(revertTimeOut);
+                        if (SmSignalSet::smPowerFaultLed == pReq->Signal)
+                        {
+                            // Deassert "system ready"
+                            retCode =
+                                ledStoreAndSet(SmSignalSet::smSystemReadyLed,
+                                               std::string("Off"));
+                            if (retCode != IPMI_CC_OK)
+                            {
+                                break;
+                            }
+                        }
+                        else if (SmSignalSet::smSystemReadyLed == pReq->Signal)
+                        {
+                            // Deassert "fault led"
+                            retCode =
+                                ledStoreAndSet(SmSignalSet::smPowerFaultLed,
+                                               std::string("Off"));
+                            if (retCode != IPMI_CC_OK)
+                            {
+                                break;
+                            }
+                        }
+                    }
+                    break;
+                    case SmActionSet::revert:
+                    {
+                        phosphor::logging::log<phosphor::logging::level::INFO>(
+                            "case SmActionSet::revert");
+                        retCode = ledRevert(pReq->Signal);
+                        if (retCode != IPMI_CC_OK)
+                        {
+                            break;
+                        }
+                    }
+                    break;
+                    default:
+                    {
+                        retCode = IPMI_CC_INVALID_FIELD_REQUEST;
+                    }
+                    break;
+                }
+                break;
+            case SmSignalSet::smFanPowerSpeed:
+            {
+                if (((pReq->Action == SmActionSet::forceAsserted) &&
+                     (*data_len != sizeof(*pReq)) && (pReq->Value > 100)) ||
+                    pReq->Instance == 0)
+                {
+                    retCode = IPMI_CC_INVALID_FIELD_REQUEST;
+                    break;
+                }
+                uint8_t pwmValue = 0;
+                switch (pReq->Action)
+                {
+                    case SmActionSet::revert:
+                    {
+                        if (mtm.revertFanPWM)
+                        {
+                            ret = mtm.disablePidControlService(false);
+                            if (ret < 0)
+                            {
+                                retCode = IPMI_CC_UNSPECIFIED_ERROR;
+                                break;
+                            }
+                            mtm.revertFanPWM = false;
+                        }
+                    }
+                    break;
+                    case SmActionSet::forceAsserted:
+                    {
+                        pwmValue = pReq->Value;
+                    } // fall-through
+                    case SmActionSet::forceDeasserted:
+                    {
+                        if (!mtm.revertFanPWM)
+                        {
+                            ret = mtm.disablePidControlService(true);
+                            if (ret < 0)
+                            {
+                                retCode = IPMI_CC_UNSPECIFIED_ERROR;
+                                break;
+                            }
+                            mtm.revertFanPWM = true;
+                        }
+                        mtm.revertTimer.start(revertTimeOut);
+                        std::string fanPwmInstancePath =
+                            fanPwmPath + std::to_string(pReq->Instance);
+
+                        ret = mtm.setProperty(
+                            fanService, fanPwmInstancePath.c_str(), fanIntf,
+                            "Value", static_cast<double>(pwmValue));
+                        if (ret < 0)
+                        {
+                            retCode = IPMI_CC_UNSPECIFIED_ERROR;
+                        }
+                    }
+                    break;
+                    default:
+                    {
+                        retCode = IPMI_CC_INVALID_FIELD_REQUEST;
+                    }
+                    break;
+                }
+            }
+            break;
+            default:
+            {
+                retCode = IPMI_CC_INVALID_FIELD_REQUEST;
+            }
+            break;
+        }
+    }
+    else
+    {
+        retCode = IPMI_CC_ILLEGAL_COMMAND;
+    }
+
+    *data_len = 0; // Only CC is return for SetSmSignal cmd
+    return retCode;
+}
+
+} // namespace ipmi
+
+void register_mtm_commands() __attribute__((constructor));
+void register_mtm_commands()
+{
+    ipmi_register_callback(
+        netfnIntcOEMGeneral,
+        static_cast<ipmi_cmd_t>(IPMINetFnIntelOemGeneralCmds::GetSmSignal),
+        NULL, ipmi::ipmi_app_mtm_get_signal, PRIVILEGE_USER);
+
+    ipmi_register_callback(
+        netfnIntcOEMGeneral,
+        static_cast<ipmi_cmd_t>(IPMINetFnIntelOemGeneralCmds::SetSmSignal),
+        NULL, ipmi::ipmi_app_mtm_set_signal, PRIVILEGE_USER);
+
+    return;
+}
diff --git a/src/smbioshandler.cpp b/src/smbioshandler.cpp
new file mode 100644
index 0000000..7510493
--- /dev/null
+++ b/src/smbioshandler.cpp
@@ -0,0 +1,501 @@
+/*
+// Copyright (c) 2018 Intel Corporation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+
+#include <ipmid/api.h>
+
+#include <commandutils.hpp>
+#include <cstdint>
+#include <iostream>
+#include <ipmid/utils.hpp>
+#include <phosphor-logging/elog-errors.hpp>
+#include <phosphor-logging/log.hpp>
+#include <sdbusplus/bus.hpp>
+#include <smbioshandler.hpp>
+#include <string>
+#include <vector>
+#include <xyz/openbmc_project/Common/error.hpp>
+
+using InternalFailure =
+    sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
+
+using level = phosphor::logging::level;
+
+constexpr const char* DBUS_PROPERTIES = "org.freedesktop.DBus.Properties";
+constexpr const char* MDRV1_PATH = "/xyz/openbmc_project/Smbios/MDR_V1";
+constexpr const char* MDRV1_INTERFACE = "xyz.openbmc_project.Smbios.MDR_V1";
+
+static void register_netfn_smbios_functions() __attribute__((constructor));
+static sdbusplus::bus::bus bus(ipmid_get_sd_bus_connection());
+
+ipmi_ret_t cmd_region_status(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+                             ipmi_request_t request, ipmi_response_t response,
+                             ipmi_data_len_t data_len, ipmi_context_t context)
+{
+    auto requestData = reinterpret_cast<const RegionStatusRequest*>(request);
+    std::vector<uint8_t> status;
+
+    if (*data_len != sizeof(RegionStatusRequest))
+    {
+        *data_len = 0;
+        return IPMI_CC_REQ_DATA_LEN_INVALID;
+    }
+
+    uint8_t regionId = requestData->regionId - 1;
+    *data_len = 0;
+
+    if (regionId >= maxMDRId)
+    {
+        phosphor::logging::log<level::ERR>("Invalid region");
+        return IPMI_CC_PARM_OUT_OF_RANGE;
+    }
+
+    std::string service = ipmi::getService(bus, MDRV1_INTERFACE, MDRV1_PATH);
+
+    auto method = bus.new_method_call(service.c_str(), MDRV1_PATH,
+                                      MDRV1_INTERFACE, "RegionStatus");
+    method.append(regionId);
+    auto reply = bus.call(method);
+    if (reply.is_method_error())
+    {
+        phosphor::logging::log<level::ERR>(
+            "Error get region status",
+            phosphor::logging::entry("SERVICE=%s", service.c_str()),
+            phosphor::logging::entry("PATH=%s", MDRV1_PATH));
+        return IPMI_CC_UNSPECIFIED_ERROR;
+    }
+    reply.read(status);
+
+    if (status.size() != sizeof(MDRState))
+    {
+        phosphor::logging::log<level::ERR>(
+            "Error get region status, return length invalid");
+        return IPMI_CC_UNSPECIFIED_ERROR;
+    }
+    *data_len = static_cast<size_t>(status.size());
+    auto dataOut = reinterpret_cast<uint8_t*>(response);
+    std::copy(&status[0], &status[*data_len], dataOut);
+    return IPMI_CC_OK;
+}
+
+int sdplus_mdrv1_get_property(
+    const std::string& name,
+    sdbusplus::message::variant<uint8_t, uint16_t>& value, std::string& service)
+{
+    auto method = bus.new_method_call(service.c_str(), MDRV1_PATH,
+                                      DBUS_PROPERTIES, "Get");
+    method.append(MDRV1_INTERFACE, name);
+    auto reply = bus.call(method);
+    if (reply.is_method_error())
+    {
+        phosphor::logging::log<level::ERR>(
+            "Error getting property, sdbusplus call failed");
+        return -1;
+    }
+    reply.read(value);
+
+    return 0;
+}
+
+static int set_regionId(uint8_t regionId, std::string& service)
+{
+    auto method = bus.new_method_call(service.c_str(), MDRV1_PATH,
+                                      DBUS_PROPERTIES, "Set");
+    sdbusplus::message::variant<uint8_t> value{regionId};
+    method.append(MDRV1_INTERFACE, "RegionId", value);
+    auto region = bus.call(method);
+    if (region.is_method_error())
+    {
+        phosphor::logging::log<level::ERR>(
+            "Error setting regionID, sdbusplus call failed");
+        return -1;
+    }
+    return 0;
+}
+
+ipmi_ret_t cmd_region_complete(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+                               ipmi_request_t request, ipmi_response_t response,
+                               ipmi_data_len_t data_len, ipmi_context_t context)
+{
+    auto requestData = reinterpret_cast<const RegionCompleteRequest*>(request);
+    uint8_t status;
+
+    sdbusplus::message::variant<uint8_t, uint16_t> value;
+
+    if (*data_len != sizeof(RegionCompleteRequest))
+    {
+        *data_len = 0;
+        return IPMI_CC_REQ_DATA_LEN_INVALID;
+    }
+
+    uint8_t regionId = requestData->regionId - 1;
+    *data_len = 0;
+
+    if (regionId >= maxMDRId)
+    {
+        phosphor::logging::log<level::ERR>("Invalid region");
+        return IPMI_CC_PARM_OUT_OF_RANGE;
+    }
+
+    std::string service = ipmi::getService(bus, MDRV1_INTERFACE, MDRV1_PATH);
+
+    if (set_regionId(regionId, service) < 0)
+    {
+        phosphor::logging::log<level::ERR>("Error setting regionId");
+        return IPMI_CC_UNSPECIFIED_ERROR;
+    }
+
+    if (0 > sdplus_mdrv1_get_property("LockPolicy", value, service))
+    {
+        phosphor::logging::log<level::ERR>("Error getting lockPolicy");
+        return IPMI_CC_UNSPECIFIED_ERROR;
+    }
+    if (regionLockUnlocked ==
+        sdbusplus::message::variant_ns::get<uint8_t>(value))
+    {
+        return IPMI_CC_PARAMETER_NOT_SUPPORT_IN_PRESENT_STATE;
+    }
+
+    if (0 > sdplus_mdrv1_get_property("SessionId", value, service))
+    {
+        phosphor::logging::log<level::ERR>("Error getting sessionId");
+        return IPMI_CC_UNSPECIFIED_ERROR;
+    }
+    if (requestData->sessionId !=
+        sdbusplus::message::variant_ns::get<uint8_t>(value))
+    {
+        return IPMI_CC_OEM_SET_IN_PROCESS;
+    }
+
+    auto method = bus.new_method_call(service.c_str(), MDRV1_PATH,
+                                      MDRV1_INTERFACE, "RegionComplete");
+
+    method.append(regionId);
+
+    auto reply = bus.call(method);
+    if (reply.is_method_error())
+    {
+        phosphor::logging::log<level::ERR>(
+            "Error set region complete",
+            phosphor::logging::entry("SERVICE=%s", service.c_str()),
+            phosphor::logging::entry("PATH=%s", MDRV1_PATH));
+        return IPMI_CC_UNSPECIFIED_ERROR;
+    }
+    reply.read(status);
+
+    if (status != 0)
+        phosphor::logging::log<level::ERR>(
+            "Error set region complete, unexpected error");
+    return IPMI_CC_UNSPECIFIED_ERROR;
+
+    return IPMI_CC_OK;
+}
+
+ipmi_ret_t cmd_region_read(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+                           ipmi_request_t request, ipmi_response_t response,
+                           ipmi_data_len_t data_len, ipmi_context_t context)
+{
+    auto requestData = reinterpret_cast<const RegionReadRequest*>(request);
+    auto responseData = reinterpret_cast<RegionReadResponse*>(response);
+    sdbusplus::message::variant<uint8_t, uint16_t> regUsedVal;
+    sdbusplus::message::variant<uint8_t, uint16_t> lockPolicyVal;
+    std::vector<uint8_t> res;
+
+    if (*data_len < sizeof(RegionReadRequest))
+    {
+        *data_len = 0;
+        return IPMI_CC_REQ_DATA_LEN_INVALID;
+    }
+
+    uint8_t regionId = requestData->regionId - 1;
+
+    *data_len = 0;
+
+    if (regionId >= maxMDRId)
+    {
+        phosphor::logging::log<level::ERR>("Invalid region");
+        return IPMI_CC_PARM_OUT_OF_RANGE;
+    }
+
+    std::string service = ipmi::getService(bus, MDRV1_INTERFACE, MDRV1_PATH);
+    // TODO to make sure the interface can get correct LockPolicy even
+    // regionId changed by another task.
+    if (set_regionId(regionId, service) < 0)
+    {
+        phosphor::logging::log<level::ERR>("Error setting regionId");
+        return IPMI_CC_UNSPECIFIED_ERROR;
+    }
+    if (0 > sdplus_mdrv1_get_property("RegionUsed", regUsedVal, service))
+    {
+        phosphor::logging::log<level::ERR>("Error getting regionUsed");
+        return IPMI_CC_UNSPECIFIED_ERROR;
+    }
+    if (requestData->offset + requestData->length >
+        sdbusplus::message::variant_ns::get<uint16_t>(regUsedVal))
+    {
+        return IPMI_CC_REQ_DATA_LEN_INVALID;
+    }
+
+    if (0 > sdplus_mdrv1_get_property("LockPolicy", lockPolicyVal, service))
+    {
+        phosphor::logging::log<level::ERR>("Error getting lockPolicy");
+        return IPMI_CC_UNSPECIFIED_ERROR;
+    }
+    if (regionLockUnlocked !=
+        sdbusplus::message::variant_ns::get<uint8_t>(lockPolicyVal))
+    {
+        return IPMI_CC_PARAMETER_NOT_SUPPORT_IN_PRESENT_STATE;
+    }
+
+    auto method = bus.new_method_call(service.c_str(), MDRV1_PATH,
+                                      MDRV1_INTERFACE, "RegionRead");
+
+    method.append(regionId, requestData->length, requestData->offset);
+
+    auto reply = bus.call(method);
+    if (reply.is_method_error())
+    {
+        phosphor::logging::log<level::ERR>(
+            "Error read region data",
+            phosphor::logging::entry("SERVICE=%s", service.c_str()),
+            phosphor::logging::entry("PATH=%s", MDRV1_PATH));
+        return IPMI_CC_UNSPECIFIED_ERROR;
+    }
+    reply.read(res);
+
+    *data_len = responseData->length = res[0];
+    responseData->updateCount = res[1];
+
+    if ((*data_len == 0) || (*data_len >= 254))
+    {
+        phosphor::logging::log<level::ERR>(
+            "Data length send from service is invalid");
+        *data_len = 0;
+        return IPMI_CC_RESPONSE_ERROR;
+    }
+
+    *data_len += 2 * sizeof(uint8_t);
+    std::copy(&res[2], &res[*data_len], responseData->data);
+    return IPMI_CC_OK;
+}
+
+ipmi_ret_t cmd_region_write(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+                            ipmi_request_t request, ipmi_response_t response,
+                            ipmi_data_len_t data_len, ipmi_context_t context)
+{
+    auto requestData = reinterpret_cast<const RegionWriteRequest*>(request);
+    uint8_t regionId = requestData->regionId - 1;
+    std::string res;
+    std::vector<uint8_t> writeData;
+    uint16_t index;
+    uint8_t tmp[255];
+
+    size_t minInputLen = &requestData->data[0] - &requestData->sessionId + 1;
+    if (*data_len < minInputLen)
+    { // this command need at least 6 bytes input
+        *data_len = 0;
+        return IPMI_CC_REQ_DATA_LEN_INVALID;
+    }
+
+    sdbusplus::message::variant<uint8_t, uint16_t> value;
+
+    *data_len = 0;
+
+    if (regionId >= maxMDRId)
+    {
+        phosphor::logging::log<level::ERR>("Invalid region");
+        return IPMI_CC_PARM_OUT_OF_RANGE;
+    }
+
+    std::string service = ipmi::getService(bus, MDRV1_INTERFACE, MDRV1_PATH);
+
+    if (set_regionId(regionId, service) < 0)
+    {
+        phosphor::logging::log<level::ERR>("Error setting regionId");
+        return IPMI_CC_UNSPECIFIED_ERROR;
+    }
+
+    if (0 > sdplus_mdrv1_get_property("LockPolicy", value, service))
+    {
+        phosphor::logging::log<level::ERR>("Error getting lockPolicy");
+        return IPMI_CC_UNSPECIFIED_ERROR;
+    }
+    if (regionLockUnlocked ==
+        sdbusplus::message::variant_ns::get<uint8_t>(value))
+    {
+        return IPMI_CC_PARAMETER_NOT_SUPPORT_IN_PRESENT_STATE;
+    }
+
+    if (0 > sdplus_mdrv1_get_property("SessionId", value, service))
+    {
+        phosphor::logging::log<level::ERR>("Error getting sessionId");
+        return IPMI_CC_UNSPECIFIED_ERROR;
+    }
+    if (requestData->sessionId !=
+        sdbusplus::message::variant_ns::get<uint8_t>(value))
+    {
+        return IPMI_CC_OEM_SET_IN_PROCESS;
+    }
+
+    std::copy(&(requestData->length), &(requestData->data[requestData->length]),
+              tmp);
+    writeData.push_back(regionId);
+    for (index = 0; index < minInputLen + requestData->length - 2; index++)
+    {
+        writeData.push_back(tmp[index]);
+    }
+
+    auto method = bus.new_method_call(service.c_str(), MDRV1_PATH,
+                                      MDRV1_INTERFACE, "RegionWrite");
+
+    method.append(writeData);
+
+    auto reply = bus.call(method);
+    if (reply.is_method_error())
+    {
+        phosphor::logging::log<level::ERR>(
+            "Error write region data",
+            phosphor::logging::entry("SERVICE=%s", service.c_str()),
+            phosphor::logging::entry("PATH=%s", MDRV1_PATH));
+        return IPMI_CC_UNSPECIFIED_ERROR;
+    }
+    reply.read(res);
+
+    if (res == "NoData")
+    {
+        return IPMI_CC_PARM_OUT_OF_RANGE;
+    }
+    else if (res != "Success")
+    {
+        phosphor::logging::log<level::ERR>(
+            "Error write region data, unexpected error");
+        return IPMI_CC_UNSPECIFIED_ERROR;
+    }
+
+    return IPMI_CC_OK;
+}
+
+ipmi_ret_t cmd_region_lock(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+                           ipmi_request_t request, ipmi_response_t response,
+                           ipmi_data_len_t data_len, ipmi_context_t context)
+{
+    auto requestData = reinterpret_cast<const RegionLockRequest*>(request);
+    uint8_t regionId = requestData->regionId - 1;
+    sdbusplus::message::variant<uint8_t, uint16_t> value;
+    auto res = reinterpret_cast<uint8_t*>(response);
+    uint8_t lockResponse;
+
+    if (*data_len != sizeof(RegionLockRequest))
+    {
+        *data_len = 0;
+        return IPMI_CC_REQ_DATA_LEN_INVALID;
+    }
+
+    *data_len = 0;
+
+    if (regionId >= maxMDRId)
+    {
+        phosphor::logging::log<level::ERR>("Invalid region");
+        return IPMI_CC_PARM_OUT_OF_RANGE;
+    }
+
+    std::string service = ipmi::getService(bus, MDRV1_INTERFACE, MDRV1_PATH);
+
+    if (set_regionId(regionId, service) < 0)
+    {
+        phosphor::logging::log<level::ERR>("Error setting regionId");
+        return IPMI_CC_UNSPECIFIED_ERROR;
+    }
+
+    if (0 > sdplus_mdrv1_get_property("LockPolicy", value, service))
+    {
+        phosphor::logging::log<level::ERR>("Error getting lockPolicy");
+        return IPMI_CC_UNSPECIFIED_ERROR;
+    }
+    if (requestData->lockPolicy == regionLockUnlocked)
+    {
+        if (regionLockUnlocked ==
+            sdbusplus::message::variant_ns::get<uint8_t>(value))
+        {
+            return IPMI_CC_PARAMETER_NOT_SUPPORT_IN_PRESENT_STATE;
+        }
+    }
+    if (regionLockUnlocked !=
+        sdbusplus::message::variant_ns::get<uint8_t>(value))
+    {
+        if (0 > sdplus_mdrv1_get_property("SessionId", value, service))
+        {
+            phosphor::logging::log<level::ERR>("Error getting sessionId");
+            return IPMI_CC_UNSPECIFIED_ERROR;
+        }
+        if (requestData->sessionId !=
+            sdbusplus::message::variant_ns::get<uint8_t>(value))
+        {
+            if (requestData->lockPolicy != regionLockStrict)
+            {
+                return IPMI_CC_OEM_SET_IN_PROCESS;
+            }
+        }
+    }
+    auto method = bus.new_method_call(service.c_str(), MDRV1_PATH,
+                                      MDRV1_INTERFACE, "RegionLock");
+
+    method.append(requestData->sessionId, regionId, requestData->lockPolicy,
+                  requestData->msTimeout);
+
+    auto reply = bus.call(method);
+    if (reply.is_method_error())
+    {
+        phosphor::logging::log<level::ERR>(
+            "Error lock region ",
+            phosphor::logging::entry("SERVICE=%s", service.c_str()),
+            phosphor::logging::entry("PATH=%s", MDRV1_PATH));
+        return IPMI_CC_UNSPECIFIED_ERROR;
+    }
+    reply.read(lockResponse);
+
+    *data_len = sizeof(lockResponse);
+    *res = lockResponse;
+    return IPMI_CC_OK;
+}
+
+static void register_netfn_smbios_functions(void)
+{
+    // MDR V1 Command
+    // <Get MDR Status Command>
+    ipmi_register_callback(NETFUN_INTEL_APP_OEM,
+                           IPMI_NETFN_INTEL_OEM_APP_CMD::MDR_STATUS, NULL,
+                           cmd_region_status, PRIVILEGE_OPERATOR);
+
+    // <Update Complete Status Command>
+    ipmi_register_callback(NETFUN_INTEL_APP_OEM,
+                           IPMI_NETFN_INTEL_OEM_APP_CMD::MDR_COMPLETE, NULL,
+                           cmd_region_complete, PRIVILEGE_OPERATOR);
+
+    // <Read MDR Command>
+    ipmi_register_callback(NETFUN_INTEL_APP_OEM,
+                           IPMI_NETFN_INTEL_OEM_APP_CMD::MDR_READ, NULL,
+                           cmd_region_read, PRIVILEGE_OPERATOR);
+
+    // <Write MDR Command>
+    ipmi_register_callback(NETFUN_INTEL_APP_OEM,
+                           IPMI_NETFN_INTEL_OEM_APP_CMD::MDR_WRITE, NULL,
+                           cmd_region_write, PRIVILEGE_OPERATOR);
+
+    // <Lock MDR Command>
+    ipmi_register_callback(NETFUN_INTEL_APP_OEM,
+                           IPMI_NETFN_INTEL_OEM_APP_CMD::MDR_LOCK, NULL,
+                           cmd_region_lock, PRIVILEGE_OPERATOR);
+}
diff --git a/src/smbiosmdrv2.cpp b/src/smbiosmdrv2.cpp
new file mode 100644
index 0000000..93ad412
--- /dev/null
+++ b/src/smbiosmdrv2.cpp
@@ -0,0 +1,1106 @@
+/*
+// Copyright (c) 2018 Intel Corporation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+
+#include <errno.h>
+#include <ipmid/api.h>
+
+#include <commandutils.hpp>
+#include <cstdint>
+#include <ipmid/utils.hpp>
+#include <phosphor-ipmi-host/ipmid.hpp>
+#include <phosphor-logging/elog-errors.hpp>
+#include <phosphor-logging/log.hpp>
+#include <sdbusplus/bus.hpp>
+#include <smbiosmdrv2.hpp>
+#include <string>
+#include <vector>
+#include <xyz/openbmc_project/Common/error.hpp>
+
+constexpr const char* DBUS_PROPERTIES = "org.freedesktop.DBus.Properties";
+constexpr const char* MDRV2_PATH = "/xyz/openbmc_project/Smbios/MDR_V2";
+constexpr const char* MDRV2_INTERFACE = "xyz.openbmc_project.Smbios.MDR_V2";
+constexpr const int LAST_AGENT_INDEX = -1;
+constexpr const uint16_t LAST_AGENT_ID = 0xFFFF;
+
+static void register_netfn_smbiosmdrv2_functions() __attribute__((constructor));
+static sdbusplus::bus::bus bus(ipmid_get_sd_bus_connection());
+
+int agentLookup(const uint16_t& agentId, const std::string& service)
+{
+    int agentIndex = -1;
+
+    if (LAST_AGENT_ID == agentId)
+    {
+        return LAST_AGENT_INDEX;
+    }
+
+    sdbusplus::message::message method = bus.new_method_call(
+        service.c_str(), MDRV2_PATH, MDRV2_INTERFACE, "AgentLookup");
+    method.append(agentId);
+    sdbusplus::message::message reply = bus.call(method);
+    if (reply.is_method_error())
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Error get agent index, sdbusplus call failed");
+        return -1;
+    }
+    reply.read(agentIndex);
+
+    return agentIndex;
+}
+
+int findLockHandle(const uint16_t& lockHandle, const std::string& service)
+{
+    int idIndex = -1;
+    sdbusplus::message::message method = bus.new_method_call(
+        service.c_str(), MDRV2_PATH, MDRV2_INTERFACE, "FindLockHandle");
+    method.append(lockHandle);
+
+    sdbusplus::message::message reply = bus.call(method);
+    if (reply.is_method_error())
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Error find lock handle",
+            phosphor::logging::entry("SERVICE=%s", service.c_str()),
+            phosphor::logging::entry("PATH=%s", MDRV2_PATH));
+        return -1;
+    }
+    reply.read(idIndex);
+
+    return idIndex;
+}
+
+int sdplusMdrv2GetProperty(const std::string& name,
+                           sdbusplus::message::variant<uint8_t>& value,
+                           const std::string& service)
+{
+    sdbusplus::message::message method = bus.new_method_call(
+        service.c_str(), MDRV2_PATH, DBUS_PROPERTIES, "Get");
+    method.append(MDRV2_INTERFACE, name);
+    sdbusplus::message::message reply = bus.call(method);
+    if (reply.is_method_error())
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Error get property, sdbusplus call failed");
+        return -1;
+    }
+    reply.read(value);
+
+    return 0;
+}
+
+int findDataId(const uint8_t* dataInfo, const size_t& len,
+               const std::string& service)
+{
+    int idIndex = -1;
+    sdbusplus::message::message method = bus.new_method_call(
+        service.c_str(), MDRV2_PATH, MDRV2_INTERFACE, "FindIdIndex");
+    std::vector<uint8_t> info;
+    for (int index = 0; index < len; index++)
+    {
+        info.push_back(dataInfo[index]);
+    }
+    method.append(info);
+
+    sdbusplus::message::message reply = bus.call(method);
+    if (reply.is_method_error())
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Error find id index",
+            phosphor::logging::entry("SERVICE=%s", service.c_str()),
+            phosphor::logging::entry("PATH=%s", MDRV2_PATH));
+        return -1;
+    }
+    reply.read(idIndex);
+
+    return idIndex;
+}
+
+ipmi_ret_t cmd_mdr2_agent_status(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+                                 ipmi_request_t request,
+                                 ipmi_response_t response,
+                                 ipmi_data_len_t data_len,
+                                 ipmi_context_t context)
+{
+    auto requestData = reinterpret_cast<const MDRiiGetAgentStatus*>(request);
+    auto dataOut = reinterpret_cast<uint8_t*>(response);
+    std::vector<uint8_t> status;
+
+    if (*data_len != sizeof(MDRiiGetAgentStatus))
+    {
+        *data_len = 0;
+        return IPMI_CC_REQ_DATA_LEN_INVALID;
+    }
+
+    *data_len = 0;
+
+    std::string service = ipmi::getService(bus, MDRV2_INTERFACE, MDRV2_PATH);
+
+    int agentIndex = agentLookup(requestData->agentId, service);
+    if (agentIndex == -1)
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Unknown agent id",
+            phosphor::logging::entry("ID=%x", requestData->agentId));
+        return IPMI_CC_PARM_OUT_OF_RANGE;
+    }
+
+    sdbusplus::message::message method = bus.new_method_call(
+        service.c_str(), MDRV2_PATH, MDRV2_INTERFACE, "AgentStatus");
+    method.append(requestData->dirVersion);
+    sdbusplus::message::message reply = bus.call(method);
+    if (reply.is_method_error())
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Error get agent status",
+            phosphor::logging::entry("SERVICE=%s", service.c_str()),
+            phosphor::logging::entry("PATH=%s", MDRV2_PATH));
+        return IPMI_CC_UNSPECIFIED_ERROR;
+    }
+    reply.read(status);
+
+    if (status.size() != sizeof(MDRiiAgentStatusResponse))
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Get agent status response length not valid");
+        return IPMI_CC_UNSPECIFIED_ERROR;
+    }
+    *data_len = static_cast<size_t>(status.size());
+    std::copy(&status[0], &status[*data_len], dataOut);
+    return IPMI_CC_OK;
+}
+
+ipmi_ret_t cmd_mdr2_get_dir(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+                            ipmi_request_t request, ipmi_response_t response,
+                            ipmi_data_len_t data_len, ipmi_context_t context)
+{
+    auto requestData = reinterpret_cast<const MDRiiGetDirRequest*>(request);
+    auto dataOut = reinterpret_cast<uint8_t*>(response);
+    std::vector<uint8_t> dirInfo;
+
+    if (*data_len != sizeof(MDRiiGetDirRequest))
+    {
+        *data_len = 0;
+        return IPMI_CC_REQ_DATA_LEN_INVALID;
+    }
+
+    *data_len = 0;
+
+    std::string service = ipmi::getService(bus, MDRV2_INTERFACE, MDRV2_PATH);
+
+    int agentIndex = agentLookup(requestData->agentId, service);
+    if (agentIndex == -1)
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Unknown agent id",
+            phosphor::logging::entry("ID=%x", requestData->agentId));
+        return IPMI_CC_PARM_OUT_OF_RANGE;
+    }
+
+    sdbusplus::message::variant<uint8_t> value = 0;
+    if (0 != sdplusMdrv2GetProperty("DirEntries", value, service))
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Error getting DirEnries");
+        return IPMI_CC_UNSPECIFIED_ERROR;
+    }
+    if (requestData->dirIndex >
+        sdbusplus::message::variant_ns::get<uint8_t>(value))
+    {
+        return IPMI_CC_PARM_OUT_OF_RANGE;
+    }
+
+    sdbusplus::message::message method = bus.new_method_call(
+        service.c_str(), MDRV2_PATH, MDRV2_INTERFACE, "GetDir");
+
+    method.append(requestData->dirIndex);
+
+    sdbusplus::message::message reply = bus.call(method);
+    if (reply.is_method_error())
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Error get dir",
+            phosphor::logging::entry("SERVICE=%s", service.c_str()),
+            phosphor::logging::entry("PATH=%s", MDRV2_PATH));
+        return IPMI_CC_UNSPECIFIED_ERROR;
+    }
+    reply.read(dirInfo);
+
+    if (dirInfo.size() < sizeof(MDRiiGetDirResponse))
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Error get dir, response length invalid");
+        return IPMI_CC_UNSPECIFIED_ERROR;
+    }
+
+    auto responseData = reinterpret_cast<MDRiiGetDirResponse*>(dirInfo.data());
+
+    *data_len = dirInfo.size();
+
+    if (*data_len > MAX_IPMI_BUFFER) // length + completion code should no more
+                                     // than MAX_IPMI_BUFFER
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Data length send from service is invalid");
+        *data_len = 0;
+        return IPMI_CC_RESPONSE_ERROR;
+    }
+
+    std::copy(&dirInfo[0], &dirInfo[*data_len], dataOut);
+
+    return IPMI_CC_OK;
+}
+
+ipmi_ret_t cmd_mdr2_get_data_info(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+                                  ipmi_request_t request,
+                                  ipmi_response_t response,
+                                  ipmi_data_len_t data_len,
+                                  ipmi_context_t context)
+{
+    auto requestData =
+        reinterpret_cast<const MDRiiGetDataInfoRequest*>(request);
+    auto dataOut = reinterpret_cast<uint8_t*>(response);
+    std::vector<uint8_t> res;
+
+    if (*data_len < sizeof(MDRiiGetDataInfoRequest))
+    {
+        *data_len = 0;
+        return IPMI_CC_REQ_DATA_LEN_INVALID;
+    }
+
+    *data_len = 0;
+
+    std::string service = ipmi::getService(bus, MDRV2_INTERFACE, MDRV2_PATH);
+
+    int agentIndex = agentLookup(requestData->agentId, service);
+    if (agentIndex == -1)
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Unknown agent id",
+            phosphor::logging::entry("ID=%x", requestData->agentId));
+        return IPMI_CC_PARM_OUT_OF_RANGE;
+    }
+
+    int idIndex =
+        findDataId(requestData->dataSetInfo.dataInfo,
+                   sizeof(requestData->dataSetInfo.dataInfo), service);
+
+    if ((idIndex < 0) || (idIndex >= maxDirEntries))
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Invalid Data ID", phosphor::logging::entry("IDINDEX=%x", idIndex));
+        return IPMI_CC_PARM_OUT_OF_RANGE;
+    }
+
+    sdbusplus::message::message method = bus.new_method_call(
+        service.c_str(), MDRV2_PATH, MDRV2_INTERFACE, "GetDataInfo");
+
+    method.append(idIndex);
+
+    sdbusplus::message::message reply = bus.call(method);
+    if (reply.is_method_error())
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Error get data info",
+            phosphor::logging::entry("SERVICE=%s", service.c_str()),
+            phosphor::logging::entry("PATH=%s", MDRV2_PATH));
+        return IPMI_CC_UNSPECIFIED_ERROR;
+    }
+    reply.read(res);
+
+    if (res.size() != sizeof(MDRiiGetDataInfoResponse))
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Get data info response length not invalid");
+        return IPMI_CC_UNSPECIFIED_ERROR;
+    }
+    *data_len = static_cast<size_t>(res.size());
+    std::copy(&res[0], &res[*data_len], dataOut);
+
+    return IPMI_CC_OK;
+}
+
+ipmi_ret_t cmd_mdr2_lock_data(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+                              ipmi_request_t request, ipmi_response_t response,
+                              ipmi_data_len_t data_len, ipmi_context_t context)
+{
+    auto requestData = reinterpret_cast<const MDRiiLockDataRequest*>(request);
+    auto responseData = reinterpret_cast<MDRiiLockDataResponse*>(response);
+
+    std::tuple<bool, uint8_t, uint16_t, uint32_t, uint32_t, uint32_t> res;
+
+    if (*data_len < sizeof(MDRiiLockDataRequest))
+    {
+        *data_len = 0;
+        return IPMI_CC_REQ_DATA_LEN_INVALID;
+    }
+
+    *data_len = 0;
+
+    std::string service = ipmi::getService(bus, MDRV2_INTERFACE, MDRV2_PATH);
+
+    int agentIndex = agentLookup(requestData->agentId, service);
+    if (agentIndex == -1)
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Unknown agent id",
+            phosphor::logging::entry("ID=%x", requestData->agentId));
+        return IPMI_CC_PARM_OUT_OF_RANGE;
+    }
+
+    int idIndex =
+        findDataId(requestData->dataSetInfo.dataInfo,
+                   sizeof(requestData->dataSetInfo.dataInfo), service);
+
+    if ((idIndex < 0) || (idIndex >= maxDirEntries))
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Invalid Data ID", phosphor::logging::entry("IDINDEX=%x", idIndex));
+        return IPMI_CC_PARM_OUT_OF_RANGE;
+    }
+
+    sdbusplus::message::message method = bus.new_method_call(
+        service.c_str(), MDRV2_PATH, MDRV2_INTERFACE, "LockData");
+
+    method.append((uint8_t)idIndex, requestData->timeout);
+
+    sdbusplus::message::message reply = bus.call(method);
+    if (reply.is_method_error())
+    {
+        if (reply.get_errno() == EBUSY)
+        {
+            phosphor::logging::log<phosphor::logging::level::ERR>(
+                "Lock Data failed - cannot lock idIndex");
+            return IPMI_CC_PARAMETER_NOT_SUPPORT_IN_PRESENT_STATE;
+        }
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Error lock data",
+            phosphor::logging::entry("SERVICE=%s", service.c_str()),
+            phosphor::logging::entry("PATH=%s", MDRV2_PATH));
+        return IPMI_CC_UNSPECIFIED_ERROR;
+    }
+    reply.read(res);
+
+    if (std::get<0>(res) == false)
+    {
+        return IPMI_CC_PARAMETER_NOT_SUPPORT_IN_PRESENT_STATE;
+    }
+
+    *data_len = sizeof(MDRiiLockDataResponse);
+
+    responseData->mdrVersion = std::get<1>(res);
+    responseData->lockHandle = std::get<2>(res);
+    responseData->dataLength = std::get<3>(res);
+    responseData->xferAddress = std::get<4>(res);
+    responseData->xferLength = std::get<5>(res);
+
+    return IPMI_CC_OK;
+}
+
+ipmi_ret_t cmd_mdr2_unlock_data(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+                                ipmi_request_t request,
+                                ipmi_response_t response,
+                                ipmi_data_len_t data_len,
+                                ipmi_context_t context)
+{
+    auto requestData = reinterpret_cast<const MDRiiUnlockDataRequest*>(request);
+    std::string resStatus;
+
+    if (*data_len != sizeof(MDRiiUnlockDataRequest))
+    {
+        *data_len = 0;
+        return IPMI_CC_REQ_DATA_LEN_INVALID;
+    }
+
+    *data_len = 0;
+
+    std::string service = ipmi::getService(bus, MDRV2_INTERFACE, MDRV2_PATH);
+
+    int agentIndex = agentLookup(requestData->agentId, service);
+    if (agentIndex == -1)
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Unknown agent id",
+            phosphor::logging::entry("ID=%x", requestData->agentId));
+        return IPMI_CC_PARM_OUT_OF_RANGE;
+    }
+
+    int idIndex = findLockHandle(requestData->lockHandle, service);
+
+    if ((idIndex < 0) || (idIndex >= maxDirEntries))
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Invalid Data ID", phosphor::logging::entry("IDINDEX=%x", idIndex));
+        return IPMI_CC_PARM_OUT_OF_RANGE;
+    }
+
+    sdbusplus::message::message method = bus.new_method_call(
+        service.c_str(), MDRV2_PATH, MDRV2_INTERFACE, "UnLockData");
+    method.append((uint8_t)idIndex);
+
+    sdbusplus::message::message reply = bus.call(method);
+    if (reply.is_method_error())
+    {
+        if (reply.get_errno() == EBUSY)
+        {
+            phosphor::logging::log<phosphor::logging::level::ERR>(
+                "Unlock Data failed - cannot unlock idIndex");
+            return IPMI_CC_PARAMETER_NOT_SUPPORT_IN_PRESENT_STATE;
+        }
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Error unlock data",
+            phosphor::logging::entry("SERVICE=%s", service.c_str()),
+            phosphor::logging::entry("PATH=%s", MDRV2_PATH));
+        return IPMI_CC_UNSPECIFIED_ERROR;
+    }
+    reply.read(resStatus);
+
+    if (resStatus != "success")
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Agent unlock Invalid lock status.");
+        return IPMI_CC_UNSPECIFIED_ERROR;
+    }
+
+    return IPMI_CC_OK;
+}
+
+ipmi_ret_t cmd_mdr2_get_data_block(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+                                   ipmi_request_t request,
+                                   ipmi_response_t response,
+                                   ipmi_data_len_t data_len,
+                                   ipmi_context_t context)
+{
+    auto requestData =
+        reinterpret_cast<const MDRiiGetDataBlockRequest*>(request);
+    auto responseData = reinterpret_cast<MDRiiGetDataBlockResponse*>(response);
+    std::tuple<uint8_t, uint32_t, uint32_t, std::vector<uint8_t>> res;
+    std::vector<uint8_t> resData;
+    uint8_t status = 1;
+
+    if (*data_len != sizeof(MDRiiGetDataBlockRequest))
+    {
+        *data_len = 0;
+        return IPMI_CC_REQ_DATA_LEN_INVALID;
+    }
+
+    *data_len = 0;
+
+    std::string service = ipmi::getService(bus, MDRV2_INTERFACE, MDRV2_PATH);
+
+    int agentIndex = agentLookup(requestData->agentId, service);
+    if (agentIndex == -1)
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Unknown agent id",
+            phosphor::logging::entry("ID=%x", requestData->agentId));
+        return IPMI_CC_PARM_OUT_OF_RANGE;
+    }
+
+    int idIndex = findLockHandle(requestData->lockHandle, service);
+
+    if ((idIndex < 0) || (idIndex >= maxDirEntries))
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Invalid Data ID", phosphor::logging::entry("IDINDEX=%x", idIndex));
+        return IPMI_CC_PARM_OUT_OF_RANGE;
+    }
+
+    sdbusplus::message::message method = bus.new_method_call(
+        service.c_str(), MDRV2_PATH, MDRV2_INTERFACE, "GetDataBlock");
+    method.append((uint8_t)idIndex, requestData->xferOffset,
+                  requestData->xferLength);
+
+    sdbusplus::message::message reply = bus.call(method);
+    if (reply.is_method_error())
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Error get data block",
+            phosphor::logging::entry("SERVICE=%s", service.c_str()),
+            phosphor::logging::entry("PATH=%s", MDRV2_PATH));
+        return IPMI_CC_UNSPECIFIED_ERROR;
+    }
+    reply.read(res);
+
+    // Get the status of get data block, 0 means succeed
+    status = std::get<0>(res);
+    if (status == 1)
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Request data offset is outside of range.");
+        return IPMI_CC_CANNOT_RETURN_NUMBER_OF_REQUESTED_DATA_BYTES;
+    }
+    else if (status != 0)
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Get data block unexpected error.");
+        return IPMI_CC_UNSPECIFIED_ERROR;
+    }
+
+    responseData->xferLength = std::get<1>(res);
+    if (responseData->xferLength > requestData->xferLength)
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Get data block unexpected error.");
+        return IPMI_CC_UNSPECIFIED_ERROR;
+    }
+
+    responseData->checksum = std::get<2>(res);
+
+    resData = std::get<3>(res);
+
+    *data_len = sizeof(responseData->xferLength) +
+                sizeof(responseData->checksum) + resData.size();
+
+    if (*data_len > MAX_IPMI_BUFFER) // length + completion code should no more
+                                     // than MAX_IPMI_BUFFER
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Data length send from service is invalid");
+        *data_len = 0;
+        return IPMI_CC_RESPONSE_ERROR;
+    }
+
+    std::copy(resData.begin(), resData.end(), responseData->data);
+
+    return IPMI_CC_OK;
+}
+
+ipmi_ret_t cmd_mdr2_send_dir(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+                             ipmi_request_t request, ipmi_response_t response,
+                             ipmi_data_len_t data_len, ipmi_context_t context)
+{
+    auto requestData = reinterpret_cast<const MDRiiSendDirRequest*>(request);
+    std::vector<uint8_t> idVector;
+    bool teminate = false;
+
+    if (*data_len != sizeof(MDRiiSendDirRequest))
+    {
+        *data_len = 0;
+        return IPMI_CC_REQ_DATA_LEN_INVALID;
+    }
+
+    *data_len = 0;
+
+    std::string service = ipmi::getService(bus, MDRV2_INTERFACE, MDRV2_PATH);
+
+    int agentIndex = agentLookup(requestData->agentId, service);
+    if (agentIndex == -1)
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Unknown agent id",
+            phosphor::logging::entry("ID=%x", requestData->agentId));
+        return IPMI_CC_PARM_OUT_OF_RANGE;
+    }
+
+    if ((requestData->dirIndex + requestData->returnedEntries) > maxDirEntries)
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Too many directory entries");
+        return IPMI_CC_STORGE_LEAK;
+    }
+
+    sdbusplus::message::message method = bus.new_method_call(
+        service.c_str(), MDRV2_PATH, MDRV2_INTERFACE, "SendDir");
+    method.append(requestData->dirVersion, requestData->dirIndex,
+                  requestData->returnedEntries, requestData->remainingEntries);
+    uint8_t* reqPoint;
+    for (int index = 0; index < requestData->returnedEntries; index++)
+    {
+        reqPoint = (uint8_t*)&(requestData->data[index]);
+        std::copy(reqPoint, sizeof(Mdr2DirEntry) + reqPoint, idVector.data());
+    }
+    method.append(idVector);
+
+    sdbusplus::message::message reply = bus.call(method);
+    if (reply.is_method_error())
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Error send dir",
+            phosphor::logging::entry("SERVICE=%s", service.c_str()),
+            phosphor::logging::entry("PATH=%s", MDRV2_PATH));
+        return IPMI_CC_UNSPECIFIED_ERROR;
+    }
+    reply.read(teminate);
+
+    *data_len = 1;
+    if (teminate == false)
+        *(static_cast<uint8_t*>(response)) = 0;
+    else
+        *(static_cast<uint8_t*>(response)) = 1;
+    return IPMI_CC_OK;
+}
+
+ipmi_ret_t cmd_mdr2_data_info_offer(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+                                    ipmi_request_t request,
+                                    ipmi_response_t response,
+                                    ipmi_data_len_t data_len,
+                                    ipmi_context_t context)
+{
+    auto requestData = reinterpret_cast<const MDRiiOfferDataInfo*>(request);
+    auto dataOut = reinterpret_cast<uint8_t*>(response);
+    std::vector<uint8_t> dataInfo;
+
+    if (*data_len != sizeof(MDRiiOfferDataInfo))
+    {
+        *data_len = 0;
+        return IPMI_CC_REQ_DATA_LEN_INVALID;
+    }
+
+    *data_len = 0;
+
+    std::string service = ipmi::getService(bus, MDRV2_INTERFACE, MDRV2_PATH);
+
+    int agentIndex = agentLookup(requestData->agentId, service);
+    if (agentIndex == -1)
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Unknown agent id",
+            phosphor::logging::entry("ID=%x", requestData->agentId));
+        return IPMI_CC_PARM_OUT_OF_RANGE;
+    }
+
+    sdbusplus::message::message method = bus.new_method_call(
+        service.c_str(), MDRV2_PATH, MDRV2_INTERFACE, "GetDataOffer");
+
+    sdbusplus::message::message reply = bus.call(method);
+    if (reply.is_method_error())
+    {
+        if (reply.get_errno() == EBUSY)
+        {
+            phosphor::logging::log<phosphor::logging::level::ERR>(
+                "Send data info offer failed - not available to update data "
+                "into agent at present");
+            return IPMI_CC_PARAMETER_NOT_SUPPORT_IN_PRESENT_STATE;
+        }
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Error send data info offer",
+            phosphor::logging::entry("SERVICE=%s", service.c_str()),
+            phosphor::logging::entry("PATH=%s", MDRV2_PATH));
+        return IPMI_CC_UNSPECIFIED_ERROR;
+    }
+    reply.read(dataInfo);
+    if (dataInfo.size() != sizeof(MDRiiOfferDataInfoResponse))
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Error send data info offer, return length invalid");
+        return IPMI_CC_UNSPECIFIED_ERROR;
+    }
+
+    *data_len = dataInfo.size();
+    std::copy(dataInfo.begin(), dataInfo.end(), dataOut);
+    return IPMI_CC_OK;
+}
+
+ipmi_ret_t cmd_mdr2_send_data_info(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+                                   ipmi_request_t request,
+                                   ipmi_response_t response,
+                                   ipmi_data_len_t data_len,
+                                   ipmi_context_t context)
+{
+    auto requestData =
+        reinterpret_cast<const MDRiiSendDataInfoRequest*>(request);
+    bool entryChanged = true;
+
+    if (*data_len != sizeof(MDRiiSendDataInfoRequest))
+    {
+        *data_len = 0;
+        return IPMI_CC_REQ_DATA_LEN_INVALID;
+    }
+
+    *data_len = 0;
+
+    if (requestData->dataLength > smbiosTableStorageSize)
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Requested data length is out of SMBIOS Table storage size.");
+        return IPMI_CC_PARM_OUT_OF_RANGE;
+    }
+
+    std::string service = ipmi::getService(bus, MDRV2_INTERFACE, MDRV2_PATH);
+
+    int agentIndex = agentLookup(requestData->agentId, service);
+    if (agentIndex == -1)
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Unknown agent id",
+            phosphor::logging::entry("ID=%x", requestData->agentId));
+        return IPMI_CC_PARM_OUT_OF_RANGE;
+    }
+
+    int idIndex =
+        findDataId(requestData->dataSetInfo.dataInfo,
+                   sizeof(requestData->dataSetInfo.dataInfo), service);
+
+    if ((idIndex < 0) || (idIndex >= maxDirEntries))
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Invalid Data ID", phosphor::logging::entry("IDINDEX=%x", idIndex));
+        return IPMI_CC_PARM_OUT_OF_RANGE;
+    }
+
+    sdbusplus::message::message method = bus.new_method_call(
+        service.c_str(), MDRV2_PATH, MDRV2_INTERFACE, "SendDataInfo");
+
+    method.append((uint8_t)idIndex, requestData->validFlag,
+                  requestData->dataLength, requestData->dataVersion,
+                  requestData->timeStamp);
+
+    sdbusplus::message::message reply = bus.call(method);
+    if (reply.is_method_error())
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Error send data info",
+            phosphor::logging::entry("SERVICE=%s", service.c_str()),
+            phosphor::logging::entry("PATH=%s", MDRV2_PATH));
+        return IPMI_CC_UNSPECIFIED_ERROR;
+    }
+    reply.read(entryChanged);
+
+    *data_len = 1;
+
+    if (entryChanged)
+    {
+        *(static_cast<uint8_t*>(response)) = 1;
+    }
+    else
+    {
+        *(static_cast<uint8_t*>(response)) = 0;
+    }
+
+    return IPMI_CC_OK;
+}
+
+ipmi_ret_t cmd_mdr2_data_start(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+                               ipmi_request_t request, ipmi_response_t response,
+                               ipmi_data_len_t data_len, ipmi_context_t context)
+{
+    auto requestData = reinterpret_cast<const MDRiiDataStartRequest*>(request);
+    auto responseData = reinterpret_cast<MDRiiDataStartResponse*>(response);
+    std::vector<uint8_t> idVector;
+
+    if (*data_len != sizeof(MDRiiDataStartRequest))
+    {
+        *data_len = 0;
+        return IPMI_CC_REQ_DATA_LEN_INVALID;
+    }
+
+    *data_len = 0;
+
+    if (requestData->dataLength > smbiosTableStorageSize)
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Requested data length is out of SMBIOS Table storage size.");
+        return IPMI_CC_PARM_OUT_OF_RANGE;
+    }
+
+    if ((requestData->xferLength + requestData->xferAddress) > mdriiSMSize)
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Invalid data address and size");
+        return IPMI_CC_PARM_OUT_OF_RANGE;
+    }
+
+    std::string service = ipmi::getService(bus, MDRV2_INTERFACE, MDRV2_PATH);
+
+    int agentIndex = agentLookup(requestData->agentId, service);
+    if (agentIndex == -1)
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Unknown agent id",
+            phosphor::logging::entry("ID=%x", requestData->agentId));
+        return IPMI_CC_PARM_OUT_OF_RANGE;
+    }
+
+    int idIndex =
+        findDataId(requestData->dataSetInfo.dataInfo,
+                   sizeof(requestData->dataSetInfo.dataInfo), service);
+
+    if ((idIndex < 0) || (idIndex >= maxDirEntries))
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Invalid Data ID", phosphor::logging::entry("IDINDEX=%x", idIndex));
+        return IPMI_CC_PARM_OUT_OF_RANGE;
+    }
+
+    sdbusplus::message::message method = bus.new_method_call(
+        service.c_str(), MDRV2_PATH, MDRV2_INTERFACE, "DataStart");
+
+    for (uint8_t infoIndex = 0; infoIndex < sizeof(DataIdStruct); infoIndex++)
+    {
+        idVector.push_back(requestData->dataSetInfo.dataInfo[infoIndex]);
+    }
+    method.append((uint8_t)idIndex, idVector, requestData->dataLength,
+                  requestData->xferAddress, requestData->xferLength,
+                  requestData->timeout);
+
+    sdbusplus::message::message reply = bus.call(method);
+    if (reply.is_method_error())
+    {
+        int errNumber = reply.get_errno();
+        if (errNumber == ENOMEM)
+        {
+            phosphor::logging::log<phosphor::logging::level::ERR>(
+                "Send data start failed - cannot map share memory");
+            return IPMI_CC_UNSPECIFIED_ERROR;
+        }
+        else if (errNumber == EINVAL)
+        {
+            phosphor::logging::log<phosphor::logging::level::ERR>(
+                "Invalid data address and size");
+            return IPMI_CC_PARM_OUT_OF_RANGE;
+        }
+        else
+        {
+            phosphor::logging::log<phosphor::logging::level::ERR>(
+                "Error Send Data Start",
+                phosphor::logging::entry("SERVICE=%s", service.c_str()),
+                phosphor::logging::entry("PATH=%s", MDRV2_PATH));
+            return IPMI_CC_UNSPECIFIED_ERROR;
+        }
+    }
+    uint8_t xferStartAck = 0;
+    uint16_t sessionHandle = 0;
+    reply.read(xferStartAck, sessionHandle);
+    responseData->sessionHandle = sessionHandle;
+    responseData->xferStartAck = xferStartAck;
+    if (responseData->xferStartAck == 0)
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Send data start unexpected error");
+        return IPMI_CC_UNSPECIFIED_ERROR;
+    }
+
+    *data_len = sizeof(MDRiiDataStartResponse);
+    return IPMI_CC_OK;
+}
+
+ipmi_ret_t cmd_mdr2_data_done(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+                              ipmi_request_t request, ipmi_response_t response,
+                              ipmi_data_len_t data_len, ipmi_context_t context)
+{
+    auto requestData = reinterpret_cast<const MDRiiDataDoneRequest*>(request);
+    std::string resStatus;
+
+    if (*data_len != sizeof(MDRiiDataDoneRequest))
+    {
+        *data_len = 0;
+        return IPMI_CC_REQ_DATA_LEN_INVALID;
+    }
+
+    *data_len = 0;
+
+    std::string service = ipmi::getService(bus, MDRV2_INTERFACE, MDRV2_PATH);
+
+    int agentIndex = agentLookup(requestData->agentId, service);
+    if (agentIndex == -1)
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Unknown agent id",
+            phosphor::logging::entry("ID=%x", requestData->agentId));
+        return IPMI_CC_PARM_OUT_OF_RANGE;
+    }
+
+    int idIndex = findLockHandle(requestData->lockHandle, service);
+
+    if ((idIndex < 0) || (idIndex >= maxDirEntries))
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Invalid Data ID", phosphor::logging::entry("IDINDEX=%x", idIndex));
+        return IPMI_CC_PARM_OUT_OF_RANGE;
+    }
+
+    sdbusplus::message::message method = bus.new_method_call(
+        service.c_str(), MDRV2_PATH, MDRV2_INTERFACE, "DataDone");
+    method.append((uint8_t)idIndex);
+
+    sdbusplus::message::message reply = bus.call(method);
+    if (reply.is_method_error())
+    {
+        if (reply.get_errno() == EBUSY)
+        {
+            phosphor::logging::log<phosphor::logging::level::ERR>(
+                "Send data done failed - cannot unlock idIndex");
+            return IPMI_CC_DESTINATION_UNAVAILABLE;
+        }
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Error Send Data done",
+            phosphor::logging::entry("SERVICE=%s", service.c_str()),
+            phosphor::logging::entry("PATH=%s", MDRV2_PATH));
+        return IPMI_CC_UNSPECIFIED_ERROR;
+    }
+    reply.read(resStatus);
+
+    if (resStatus != "success")
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Data done failure.");
+        return IPMI_CC_DESTINATION_UNAVAILABLE;
+    }
+
+    return IPMI_CC_OK;
+}
+
+ipmi_ret_t cmd_mdr2_send_data_block(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+                                    ipmi_request_t request,
+                                    ipmi_response_t response,
+                                    ipmi_data_len_t data_len,
+                                    ipmi_context_t context)
+{
+    auto requestData =
+        reinterpret_cast<const MDRiiSendDataBlockRequest*>(request);
+    std::string resStatus;
+
+    if (*data_len != sizeof(MDRiiSendDataBlockRequest))
+    {
+        *data_len = 0;
+        return IPMI_CC_REQ_DATA_LEN_INVALID;
+    }
+
+    *data_len = 0;
+
+    std::string service = ipmi::getService(bus, MDRV2_INTERFACE, MDRV2_PATH);
+
+    int agentIndex = agentLookup(requestData->agentId, service);
+    if (agentIndex == -1)
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Unknown agent id",
+            phosphor::logging::entry("ID=%x", requestData->agentId));
+        return IPMI_CC_PARM_OUT_OF_RANGE;
+    }
+
+    int idIndex = findLockHandle(requestData->lockHandle, service);
+
+    if ((idIndex < 0) || (idIndex >= maxDirEntries))
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Invalid Data ID", phosphor::logging::entry("IDINDEX=%x", idIndex));
+        return IPMI_CC_PARM_OUT_OF_RANGE;
+    }
+
+    sdbusplus::message::message method = bus.new_method_call(
+        service.c_str(), MDRV2_PATH, MDRV2_INTERFACE, "SendDataBlock");
+    method.append((uint8_t)idIndex, requestData->xferOffset,
+                  requestData->xferLength, requestData->checksum);
+
+    sdbusplus::message::message reply = bus.call(method);
+    if (reply.is_method_error())
+    {
+        int errNumber = reply.get_errno();
+        if (errNumber == EINVAL)
+        {
+            phosphor::logging::log<phosphor::logging::level::ERR>(
+                "Send data block Invalid checksum");
+            return IPMI_CC_OEM_INVALID_CHECKSUM;
+        }
+        else if (errNumber == ENOBUFS)
+        {
+            phosphor::logging::log<phosphor::logging::level::ERR>(
+                "Send data block Invalid offset/length");
+            return IPMI_CC_REQUEST_DATA_FIELD_LENGTH_LIMIT_EXCEEDED;
+        }
+        else if (errNumber == EBUSY)
+        {
+            phosphor::logging::log<phosphor::logging::level::ERR>(
+                "Send data block failed, other data is updating");
+            return IPMI_CC_DESTINATION_UNAVAILABLE;
+        }
+        else
+        {
+            phosphor::logging::log<phosphor::logging::level::ERR>(
+                "Error Send data block",
+                phosphor::logging::entry("SERVICE=%s", service.c_str()),
+                phosphor::logging::entry("PATH=%s", MDRV2_PATH));
+            return IPMI_CC_UNSPECIFIED_ERROR;
+        }
+    }
+    reply.read(resStatus);
+
+    if (resStatus != "success")
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "send data block failure.");
+        return IPMI_CC_DESTINATION_UNAVAILABLE;
+    }
+
+    return IPMI_CC_OK;
+}
+
+static void register_netfn_smbiosmdrv2_functions(void)
+{
+    // MDR V2 Command
+    // <Get MDRII Status Command>
+    ipmi_register_callback(NETFUN_INTEL_APP_OEM,
+                           IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_AGENT_STATUS,
+                           NULL, cmd_mdr2_agent_status, PRIVILEGE_OPERATOR);
+
+    // <Get MDRII Directory Command>
+    ipmi_register_callback(NETFUN_INTEL_APP_OEM,
+                           IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_GET_DIR, NULL,
+                           cmd_mdr2_get_dir, PRIVILEGE_OPERATOR);
+
+    // <Get MDRII Data Info Command>
+    ipmi_register_callback(NETFUN_INTEL_APP_OEM,
+                           IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_GET_DATA_INFO,
+                           NULL, cmd_mdr2_get_data_info, PRIVILEGE_OPERATOR);
+
+    // <Lock MDRII Data Command>
+    ipmi_register_callback(NETFUN_INTEL_APP_OEM,
+                           IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_LOCK_DATA, NULL,
+                           cmd_mdr2_lock_data, PRIVILEGE_OPERATOR);
+
+    // <Unlock MDRII Data Command>
+    ipmi_register_callback(NETFUN_INTEL_APP_OEM,
+                           IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_UNLOCK_DATA,
+                           NULL, cmd_mdr2_unlock_data, PRIVILEGE_OPERATOR);
+
+    // <Get MDRII Data Block Command>
+    ipmi_register_callback(NETFUN_INTEL_APP_OEM,
+                           IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_GET_DATA_BLOCK,
+                           NULL, cmd_mdr2_get_data_block, PRIVILEGE_OPERATOR);
+
+    // <Send MDRII Directory Command>
+    ipmi_register_callback(NETFUN_INTEL_APP_OEM,
+                           IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_SEND_DIR, NULL,
+                           cmd_mdr2_send_dir, PRIVILEGE_OPERATOR);
+
+    // <Send MDRII Info Offer>
+    ipmi_register_callback(
+        NETFUN_INTEL_APP_OEM,
+        IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_SEND_DATA_INFO_OFFER, NULL,
+        cmd_mdr2_data_info_offer, PRIVILEGE_OPERATOR);
+
+    // <Send MDRII Data Info>
+    ipmi_register_callback(NETFUN_INTEL_APP_OEM,
+                           IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_SEND_DATA_INFO,
+                           NULL, cmd_mdr2_send_data_info, PRIVILEGE_OPERATOR);
+
+    // <Send MDRII Data Start>
+    ipmi_register_callback(NETFUN_INTEL_APP_OEM,
+                           IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_DATA_START, NULL,
+                           cmd_mdr2_data_start, PRIVILEGE_OPERATOR);
+
+    // <Send MDRII Data Done>
+    ipmi_register_callback(NETFUN_INTEL_APP_OEM,
+                           IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_DATA_DONE, NULL,
+                           cmd_mdr2_data_done, PRIVILEGE_OPERATOR);
+
+    // <Send MDRII Data Block>
+    ipmi_register_callback(NETFUN_INTEL_APP_OEM,
+                           IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_SEND_DATA_BLOCK,
+                           NULL, cmd_mdr2_send_data_block, PRIVILEGE_OPERATOR);
+}
diff --git a/src/smbiosmdrv2handler.cpp b/src/smbiosmdrv2handler.cpp
new file mode 100644
index 0000000..da3712a
--- /dev/null
+++ b/src/smbiosmdrv2handler.cpp
@@ -0,0 +1,1444 @@
+/*
+// Copyright (c) 2018 Intel Corporation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+
+#include <errno.h>
+#include <fcntl.h>
+#include <ipmid/api.h>
+#include <limits.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <commandutils.hpp>
+#include <cstdint>
+#include <fstream>
+#include <ipmid/utils.hpp>
+#include <phosphor-logging/log.hpp>
+#include <sdbusplus/bus.hpp>
+#include <sdbusplus/message/types.hpp>
+#include <smbiosmdrv2handler.hpp>
+#include <string>
+#include <vector>
+#include <xyz/openbmc_project/Common/error.hpp>
+#include <xyz/openbmc_project/Smbios/MDR_V2/error.hpp>
+
+std::unique_ptr<MDRV2> mdrv2 = nullptr;
+
+namespace variant_ns = sdbusplus::message::variant_ns;
+
+static void register_netfn_smbiosmdrv2_functions() __attribute__((constructor));
+static sdbusplus::bus::bus bus(ipmid_get_sd_bus_connection());
+
+int MDRV2::agentLookup(const uint16_t &agentId)
+{
+    int agentIndex = -1;
+
+    if (lastAgentId == agentId)
+    {
+        return lastAgentIndex;
+    }
+
+    if (agentId == smbiosAgentId)
+    {
+        return firstAgentIndex;
+    }
+
+    return agentIndex;
+}
+
+int MDRV2::sdplusMdrv2GetProperty(const std::string &name,
+                                  sdbusplus::message::variant<uint8_t> &value,
+                                  const std::string &service)
+{
+    sdbusplus::message::message method =
+        bus.new_method_call(service.c_str(), mdrv2Path, dbusProperties, "Get");
+    method.append(mdrv2Interface, name);
+
+    sdbusplus::message::message reply = bus.call(method);
+
+    try
+    {
+        sdbusplus::message::message reply = bus.call(method);
+        reply.read(value);
+    }
+    catch (sdbusplus::exception_t &)
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Error get property, sdbusplus call failed");
+        return -1;
+    }
+
+    return 0;
+}
+
+int MDRV2::syncDirCommonData(uint8_t idIndex, uint32_t size,
+                             const std::string &service)
+{
+    std::vector<uint32_t> commonData;
+    sdbusplus::message::message method =
+        bus.new_method_call(service.c_str(), mdrv2Path, mdrv2Interface,
+                            "SynchronizeDirectoryCommonData");
+    method.append(idIndex, size);
+
+    try
+    {
+        sdbusplus::message::message reply = bus.call(method);
+        reply.read(commonData);
+    }
+    catch (sdbusplus::exception_t &)
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Error sync dir common data with service");
+        return -1;
+    }
+
+    if (commonData.size() < syncDirCommonSize)
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Error sync dir common data - data length invalid");
+        return -1;
+    }
+    smbiosDir.dir[idIndex].common.dataSetSize = commonData.at(0);
+    smbiosDir.dir[idIndex].common.dataVersion = commonData.at(1);
+    smbiosDir.dir[idIndex].common.timestamp = commonData.at(2);
+
+    return 0;
+}
+
+int MDRV2::findDataId(const uint8_t *dataInfo, const size_t &len,
+                      const std::string &service)
+{
+    int idIndex = -1;
+
+    if (dataInfo == nullptr)
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Error dataInfo, input is null point");
+        return -1;
+    }
+
+    sdbusplus::message::message method = bus.new_method_call(
+        service.c_str(), mdrv2Path, mdrv2Interface, "FindIdIndex");
+    std::vector<uint8_t> info;
+    info.resize(len);
+    std::copy(dataInfo, dataInfo + len, info.data());
+    method.append(info);
+
+    try
+    {
+        sdbusplus::message::message reply = bus.call(method);
+        reply.read(idIndex);
+    }
+    catch (sdbusplus::exception_t &)
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Error find id index",
+            phosphor::logging::entry("SERVICE=%s", service.c_str()),
+            phosphor::logging::entry("PATH=%s", mdrv2Path));
+        return -1;
+    }
+
+    return idIndex;
+}
+
+uint16_t MDRV2::getSessionHandle(Mdr2DirStruct *dir)
+{
+    if (dir == NULL)
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Empty dir point");
+        return 0;
+    }
+    dir->sessionHandle++;
+    if (dir->sessionHandle == 0)
+    {
+        dir->sessionHandle = 1;
+    }
+
+    return dir->sessionHandle;
+}
+
+int MDRV2::findLockHandle(const uint16_t &lockHandle)
+{
+    int idIndex = -1;
+
+    for (int index = 0; index < smbiosDir.dirEntries; index++)
+    {
+        if (lockHandle == smbiosDir.dir[index].lockHandle)
+        {
+            return index;
+        }
+    }
+
+    return idIndex;
+}
+
+bool MDRV2::smbiosIsUpdating(uint8_t index)
+{
+    if (index > maxDirEntries)
+    {
+        return false;
+    }
+    if (smbiosDir.dir[index].stage == MDR2SMBIOSStatusEnum::mdr2Updating)
+    {
+        return true;
+    }
+
+    return false;
+}
+
+uint32_t MDRV2::calcChecksum32(uint8_t *buf, uint32_t len)
+{
+    uint32_t sum = 0;
+
+    if (buf == nullptr)
+    {
+        return invalidChecksum;
+    }
+
+    for (uint32_t index = 0; index < len; index++)
+    {
+        sum += buf[index];
+    }
+
+    return sum;
+}
+
+ipmi_ret_t cmd_mdr2_agent_status(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+                                 ipmi_request_t request,
+                                 ipmi_response_t response,
+                                 ipmi_data_len_t data_len,
+                                 ipmi_context_t context)
+{
+    auto requestData = reinterpret_cast<const MDRiiGetAgentStatus *>(request);
+    auto responseData = reinterpret_cast<MDRiiAgentStatusResponse *>(response);
+
+    if (*data_len != sizeof(MDRiiGetAgentStatus))
+    {
+        *data_len = 0;
+        return IPMI_CC_REQ_DATA_LEN_INVALID;
+    }
+
+    *data_len = 0;
+
+    if (mdrv2 == nullptr)
+    {
+        mdrv2 = std::make_unique<MDRV2>();
+    }
+
+    int agentIndex = mdrv2->agentLookup(requestData->agentId);
+    if (agentIndex == -1)
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Unknown agent id",
+            phosphor::logging::entry("ID=%x", requestData->agentId));
+        return IPMI_CC_PARM_OUT_OF_RANGE;
+    }
+
+    responseData->mdrVersion = mdr2Version;
+    responseData->agentVersion = smbiosAgentVersion;
+    responseData->dirVersion = mdrv2->smbiosDir.dirVersion;
+    responseData->dirEntries = mdrv2->smbiosDir.dirEntries;
+
+    if (mdrv2->smbiosDir.remoteDirVersion != requestData->dirVersion)
+    {
+        mdrv2->smbiosDir.remoteDirVersion = requestData->dirVersion;
+        responseData->dataRequest =
+            static_cast<uint8_t>(DirDataRequestEnum::dirDataRequested);
+    }
+    else
+    {
+        responseData->dataRequest =
+            static_cast<uint8_t>(DirDataRequestEnum::dirDataNotRequested);
+    }
+
+    *data_len = sizeof(MDRiiAgentStatusResponse);
+
+    return IPMI_CC_OK;
+}
+
+ipmi_ret_t cmd_mdr2_get_dir(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+                            ipmi_request_t request, ipmi_response_t response,
+                            ipmi_data_len_t data_len, ipmi_context_t context)
+{
+    auto requestData = reinterpret_cast<const MDRiiGetDirRequest *>(request);
+    auto dataOut = reinterpret_cast<uint8_t *>(response);
+    std::vector<uint8_t> dirInfo;
+
+    if (*data_len != sizeof(MDRiiGetDirRequest))
+    {
+        *data_len = 0;
+        return IPMI_CC_REQ_DATA_LEN_INVALID;
+    }
+
+    *data_len = 0;
+
+    std::string service = ipmi::getService(bus, mdrv2Interface, mdrv2Path);
+
+    if (mdrv2 == nullptr)
+    {
+        mdrv2 = std::make_unique<MDRV2>();
+    }
+
+    int agentIndex = mdrv2->agentLookup(requestData->agentId);
+    if (agentIndex == -1)
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Unknown agent id",
+            phosphor::logging::entry("ID=%x", requestData->agentId));
+        return IPMI_CC_PARM_OUT_OF_RANGE;
+    }
+
+    sdbusplus::message::variant<uint8_t> value = 0;
+    if (0 != mdrv2->sdplusMdrv2GetProperty("DirectoryEntries", value, service))
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Error getting DirEnries");
+        return IPMI_CC_UNSPECIFIED_ERROR;
+    }
+    if (requestData->dirIndex > variant_ns::get<uint8_t>(value))
+    {
+        return IPMI_CC_PARM_OUT_OF_RANGE;
+    }
+
+    sdbusplus::message::message method = bus.new_method_call(
+        service.c_str(), mdrv2Path, mdrv2Interface, "GetDirectoryInformation");
+
+    method.append(requestData->dirIndex);
+
+    try
+    {
+        sdbusplus::message::message reply = bus.call(method);
+        reply.read(dirInfo);
+    }
+    catch (sdbusplus::xyz::openbmc_project::Smbios::MDR_V2::Error::
+               InvalidParameter)
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Error get dir - Invalid parameter");
+        return IPMI_CC_PARM_OUT_OF_RANGE;
+    }
+    catch (sdbusplus::exception_t &)
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Error get dir",
+            phosphor::logging::entry("SERVICE=%s", service.c_str()),
+            phosphor::logging::entry("PATH=%s", mdrv2Path));
+        return IPMI_CC_RESPONSE_ERROR;
+    }
+
+    if (dirInfo.size() < sizeof(MDRiiGetDirResponse))
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Error get dir, response length invalid");
+        return IPMI_CC_UNSPECIFIED_ERROR;
+    }
+
+    auto responseData = reinterpret_cast<MDRiiGetDirResponse *>(dirInfo.data());
+
+    *data_len = dirInfo.size();
+
+    if (*data_len > MAX_IPMI_BUFFER) // length + completion code should no more
+                                     // than MAX_IPMI_BUFFER
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Data length send from service is invalid");
+        *data_len = 0;
+        return IPMI_CC_RESPONSE_ERROR;
+    }
+
+    std::copy(&dirInfo[0], &dirInfo[*data_len], dataOut);
+
+    return IPMI_CC_OK;
+}
+
+ipmi_ret_t cmd_mdr2_send_dir(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+                             ipmi_request_t request, ipmi_response_t response,
+                             ipmi_data_len_t data_len, ipmi_context_t context)
+{
+    auto requestData = reinterpret_cast<const MDRiiSendDirRequest *>(request);
+    std::vector<uint8_t> idVector;
+    bool teminate = false;
+
+    if (*data_len != sizeof(MDRiiSendDirRequest))
+    {
+        *data_len = 0;
+        return IPMI_CC_REQ_DATA_LEN_INVALID;
+    }
+
+    *data_len = 0;
+
+    std::string service = ipmi::getService(bus, mdrv2Interface, mdrv2Path);
+
+    if (mdrv2 == nullptr)
+    {
+        mdrv2 = std::make_unique<MDRV2>();
+    }
+
+    int agentIndex = mdrv2->agentLookup(requestData->agentId);
+    if (agentIndex == -1)
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Unknown agent id",
+            phosphor::logging::entry("ID=%x", requestData->agentId));
+        return IPMI_CC_PARM_OUT_OF_RANGE;
+    }
+
+    if ((requestData->dirIndex + requestData->returnedEntries) > maxDirEntries)
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Too many directory entries");
+        return IPMI_CC_STORGE_LEAK;
+    }
+
+    sdbusplus::message::message method = bus.new_method_call(
+        service.c_str(), mdrv2Path, mdrv2Interface, "SendDirectoryInformation");
+    method.append(requestData->dirVersion, requestData->dirIndex,
+                  requestData->returnedEntries, requestData->remainingEntries);
+    uint8_t *reqPoint;
+    for (int index = 0; index < requestData->returnedEntries; index++)
+    {
+        reqPoint = (uint8_t *)&(requestData->data[index]);
+        std::copy(reqPoint, sizeof(Mdr2DirEntry) + reqPoint, idVector.data());
+    }
+    method.append(idVector);
+
+    try
+    {
+        sdbusplus::message::message reply = bus.call(method);
+        reply.read(teminate);
+    }
+    catch (sdbusplus::xyz::openbmc_project::Smbios::MDR_V2::Error::
+               InvalidParameter)
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Error send dir - Invalid parameter");
+        return IPMI_CC_PARM_OUT_OF_RANGE;
+    }
+    catch (sdbusplus::exception_t &)
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Error send dir",
+            phosphor::logging::entry("SERVICE=%s", service.c_str()),
+            phosphor::logging::entry("PATH=%s", mdrv2Path));
+        return IPMI_CC_RESPONSE_ERROR;
+    }
+
+    *data_len = 1;
+    if (teminate == false)
+        *(static_cast<uint8_t *>(response)) = 0;
+    else
+        *(static_cast<uint8_t *>(response)) = 1;
+    return IPMI_CC_OK;
+}
+
+ipmi_ret_t cmd_mdr2_get_data_info(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+                                  ipmi_request_t request,
+                                  ipmi_response_t response,
+                                  ipmi_data_len_t data_len,
+                                  ipmi_context_t context)
+{
+    auto requestData =
+        reinterpret_cast<const MDRiiGetDataInfoRequest *>(request);
+    auto dataOut = reinterpret_cast<uint8_t *>(response);
+    std::vector<uint8_t> res;
+
+    if (*data_len < sizeof(MDRiiGetDataInfoRequest))
+    {
+        *data_len = 0;
+        return IPMI_CC_REQ_DATA_LEN_INVALID;
+    }
+
+    *data_len = 0;
+
+    std::string service = ipmi::getService(bus, mdrv2Interface, mdrv2Path);
+
+    if (mdrv2 == nullptr)
+    {
+        mdrv2 = std::make_unique<MDRV2>();
+    }
+
+    int agentIndex = mdrv2->agentLookup(requestData->agentId);
+    if (agentIndex == -1)
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Unknown agent id",
+            phosphor::logging::entry("ID=%x", requestData->agentId));
+        return IPMI_CC_PARM_OUT_OF_RANGE;
+    }
+
+    int idIndex =
+        mdrv2->findDataId(requestData->dataSetInfo.dataInfo,
+                          sizeof(requestData->dataSetInfo.dataInfo), service);
+
+    if ((idIndex < 0) || (idIndex >= maxDirEntries))
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Invalid Data ID", phosphor::logging::entry("IDINDEX=%x", idIndex));
+        return IPMI_CC_PARM_OUT_OF_RANGE;
+    }
+
+    sdbusplus::message::message method = bus.new_method_call(
+        service.c_str(), mdrv2Path, mdrv2Interface, "GetDataInformation");
+
+    method.append(idIndex);
+
+    try
+    {
+        sdbusplus::message::message reply = bus.call(method);
+        reply.read(res);
+    }
+    catch (sdbusplus::exception_t &)
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Error get data info",
+            phosphor::logging::entry("SERVICE=%s", service.c_str()),
+            phosphor::logging::entry("PATH=%s", mdrv2Path));
+        return IPMI_CC_RESPONSE_ERROR;
+    }
+
+    if (res.size() != sizeof(MDRiiGetDataInfoResponse))
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Get data info response length not invalid");
+        return IPMI_CC_UNSPECIFIED_ERROR;
+    }
+    *data_len = static_cast<size_t>(res.size());
+    std::copy(&res[0], &res[*data_len], dataOut);
+
+    return IPMI_CC_OK;
+}
+
+// Offer a agent ID to get the "Data Set ID"
+ipmi_ret_t cmd_mdr2_data_info_offer(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+                                    ipmi_request_t request,
+                                    ipmi_response_t response,
+                                    ipmi_data_len_t data_len,
+                                    ipmi_context_t context)
+{
+    auto requestData = reinterpret_cast<const MDRiiOfferDataInfo *>(request);
+    auto dataOut = reinterpret_cast<uint8_t *>(response);
+    std::vector<uint8_t> dataInfo;
+
+    if (*data_len != sizeof(MDRiiOfferDataInfo))
+    {
+        *data_len = 0;
+        return IPMI_CC_REQ_DATA_LEN_INVALID;
+    }
+
+    *data_len = 0;
+
+    std::string service = ipmi::getService(bus, mdrv2Interface, mdrv2Path);
+
+    if (mdrv2 == nullptr)
+    {
+        mdrv2 = std::make_unique<MDRV2>();
+    }
+
+    int agentIndex = mdrv2->agentLookup(requestData->agentId);
+    if (agentIndex == -1)
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Unknown agent id",
+            phosphor::logging::entry("ID=%x", requestData->agentId));
+        return IPMI_CC_PARM_OUT_OF_RANGE;
+    }
+
+    sdbusplus::message::message method = bus.new_method_call(
+        service.c_str(), mdrv2Path, mdrv2Interface, "GetDataOffer");
+
+    try
+    {
+        sdbusplus::message::message reply = bus.call(method);
+        reply.read(dataInfo);
+    }
+    catch (
+        sdbusplus::xyz::openbmc_project::Smbios::MDR_V2::Error::UpdateInProgress
+            &)
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Send data info offer failed - not available to update data "
+            "into agent at present");
+        return IPMI_CC_PARAMETER_NOT_SUPPORT_IN_PRESENT_STATE;
+    }
+    catch (sdbusplus::exception_t &)
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Error send data info offer",
+            phosphor::logging::entry("SERVICE=%s", service.c_str()),
+            phosphor::logging::entry("PATH=%s", mdrv2Path));
+        return IPMI_CC_RESPONSE_ERROR;
+    }
+
+    if (dataInfo.size() != sizeof(MDRiiOfferDataInfoResponse))
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Error send data info offer, return length invalid");
+        return IPMI_CC_UNSPECIFIED_ERROR;
+    }
+
+    *data_len = dataInfo.size();
+    std::copy(dataInfo.begin(), dataInfo.end(), dataOut);
+    return IPMI_CC_OK;
+}
+
+ipmi_ret_t cmd_mdr2_send_data_info(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+                                   ipmi_request_t request,
+                                   ipmi_response_t response,
+                                   ipmi_data_len_t data_len,
+                                   ipmi_context_t context)
+{
+    auto requestData =
+        reinterpret_cast<const MDRiiSendDataInfoRequest *>(request);
+    bool entryChanged = true;
+
+    if (*data_len != sizeof(MDRiiSendDataInfoRequest))
+    {
+        *data_len = 0;
+        return IPMI_CC_REQ_DATA_LEN_INVALID;
+    }
+
+    *data_len = 0;
+
+    if (requestData->dataLength > smbiosTableStorageSize)
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Requested data length is out of SMBIOS Table storage size.");
+        return IPMI_CC_PARM_OUT_OF_RANGE;
+    }
+
+    std::string service = ipmi::getService(bus, mdrv2Interface, mdrv2Path);
+
+    if (mdrv2 == nullptr)
+    {
+        mdrv2 = std::make_unique<MDRV2>();
+    }
+
+    int agentIndex = mdrv2->agentLookup(requestData->agentId);
+    if (agentIndex == -1)
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Unknown agent id",
+            phosphor::logging::entry("ID=%x", requestData->agentId));
+        return IPMI_CC_PARM_OUT_OF_RANGE;
+    }
+
+    int idIndex =
+        mdrv2->findDataId(requestData->dataSetInfo.dataInfo,
+                          sizeof(requestData->dataSetInfo.dataInfo), service);
+
+    if ((idIndex < 0) || (idIndex >= maxDirEntries))
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Invalid Data ID", phosphor::logging::entry("IDINDEX=%x", idIndex));
+        return IPMI_CC_PARM_OUT_OF_RANGE;
+    }
+
+    sdbusplus::message::message method = bus.new_method_call(
+        service.c_str(), mdrv2Path, mdrv2Interface, "SendDataInformation");
+
+    method.append((uint8_t)idIndex, requestData->validFlag,
+                  requestData->dataLength, requestData->dataVersion,
+                  requestData->timeStamp);
+
+    try
+    {
+        sdbusplus::message::message reply = bus.call(method);
+        reply.read(entryChanged);
+    }
+    catch (sdbusplus::exception_t &)
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Error send data info",
+            phosphor::logging::entry("SERVICE=%s", service.c_str()),
+            phosphor::logging::entry("PATH=%s", mdrv2Path));
+        return IPMI_CC_RESPONSE_ERROR;
+    }
+
+    *data_len = 1;
+
+    if (entryChanged)
+    {
+        *(static_cast<uint8_t *>(response)) = 1;
+    }
+    else
+    {
+        *(static_cast<uint8_t *>(response)) = 0;
+    }
+
+    return IPMI_CC_OK;
+}
+
+ipmi_ret_t cmd_mdr2_get_data_block(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+                                   ipmi_request_t request,
+                                   ipmi_response_t response,
+                                   ipmi_data_len_t data_len,
+                                   ipmi_context_t context)
+{
+    auto requestData =
+        reinterpret_cast<const MDRiiGetDataBlockRequest *>(request);
+    auto responseData = reinterpret_cast<MDRiiGetDataBlockResponse *>(response);
+    std::tuple<uint8_t, uint32_t, uint32_t, std::vector<uint8_t>> res;
+    std::vector<uint8_t> resData;
+    uint8_t status = 1;
+
+    if (*data_len != sizeof(MDRiiGetDataBlockRequest))
+    {
+        *data_len = 0;
+        return IPMI_CC_REQ_DATA_LEN_INVALID;
+    }
+
+    *data_len = 0;
+
+    std::string service = ipmi::getService(bus, mdrv2Interface, mdrv2Path);
+
+    if (mdrv2 == nullptr)
+    {
+        mdrv2 = std::make_unique<MDRV2>();
+    }
+
+    int agentIndex = mdrv2->agentLookup(requestData->agentId);
+    if (agentIndex == -1)
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Unknown agent id",
+            phosphor::logging::entry("ID=%x", requestData->agentId));
+        return IPMI_CC_PARM_OUT_OF_RANGE;
+    }
+
+    int idIndex = mdrv2->findLockHandle(requestData->lockHandle);
+
+    if ((idIndex < 0) || (idIndex >= maxDirEntries))
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Invalid Data ID", phosphor::logging::entry("IDINDEX=%x", idIndex));
+        return IPMI_CC_PARM_OUT_OF_RANGE;
+    }
+
+    if (requestData->xferOffset >= mdrv2->smbiosDir.dir[idIndex].common.size)
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Offset is outside of range.");
+        return IPMI_CC_PARM_OUT_OF_RANGE;
+    }
+
+    size_t outSize =
+        (requestData->xferLength > mdrv2->smbiosDir.dir[idIndex].xferSize)
+            ? mdrv2->smbiosDir.dir[idIndex].xferSize
+            : requestData->xferLength;
+    if (outSize > UINT_MAX - requestData->xferOffset)
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Out size and offset are out of range");
+        return IPMI_CC_PARM_OUT_OF_RANGE;
+    }
+    if ((requestData->xferOffset + outSize) >
+        mdrv2->smbiosDir.dir[idIndex].common.size)
+    {
+        outSize =
+            mdrv2->smbiosDir.dir[idIndex].common.size - requestData->xferOffset;
+    }
+
+    responseData->xferLength = outSize;
+    if (responseData->xferLength > requestData->xferLength)
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Get data block unexpected error.");
+        return IPMI_CC_UNSPECIFIED_ERROR;
+    }
+
+    if ((requestData->xferOffset + outSize) >
+        UINT_MAX -
+            reinterpret_cast<size_t>(mdrv2->smbiosDir.dir[idIndex].dataStorage))
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Input data to calculate checksum is out of range");
+        return IPMI_CC_PARM_OUT_OF_RANGE;
+    }
+
+    uint32_t u32Checksum = mdrv2->calcChecksum32(
+        mdrv2->smbiosDir.dir[idIndex].dataStorage + requestData->xferOffset,
+        outSize);
+    if (u32Checksum == invalidChecksum)
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Get data block failed - invalid checksum");
+        return IPMI_CC_OEM_INVALID_CHECKSUM;
+    }
+    responseData->checksum = u32Checksum;
+
+    *data_len = sizeof(responseData->xferLength) +
+                sizeof(responseData->checksum) + outSize;
+
+    if (*data_len > MAX_IPMI_BUFFER) // length + completion code should no more
+                                     // than MAX_IPMI_BUFFER
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Data length send from service is invalid");
+        *data_len = 0;
+        return IPMI_CC_RESPONSE_ERROR;
+    }
+
+    std::copy(
+        &mdrv2->smbiosDir.dir[idIndex].dataStorage[requestData->xferOffset],
+        &mdrv2->smbiosDir.dir[idIndex]
+             .dataStorage[requestData->xferOffset + outSize],
+        responseData->data);
+
+    return IPMI_CC_OK;
+}
+
+ipmi_ret_t cmd_mdr2_send_data_block(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+                                    ipmi_request_t request,
+                                    ipmi_response_t response,
+                                    ipmi_data_len_t data_len,
+                                    ipmi_context_t context)
+{
+    auto requestData =
+        reinterpret_cast<const MDRiiSendDataBlockRequest *>(request);
+
+    if (*data_len != sizeof(MDRiiSendDataBlockRequest))
+    {
+        *data_len = 0;
+        return IPMI_CC_REQ_DATA_LEN_INVALID;
+    }
+
+    *data_len = 0;
+
+    std::string service = ipmi::getService(bus, mdrv2Interface, mdrv2Path);
+
+    if (mdrv2 == nullptr)
+    {
+        mdrv2 = std::make_unique<MDRV2>();
+    }
+
+    int agentIndex = mdrv2->agentLookup(requestData->agentId);
+    if (agentIndex == -1)
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Unknown agent id",
+            phosphor::logging::entry("ID=%x", requestData->agentId));
+        return IPMI_CC_PARM_OUT_OF_RANGE;
+    }
+
+    int idIndex = mdrv2->findLockHandle(requestData->lockHandle);
+
+    if ((idIndex < 0) || (idIndex >= maxDirEntries))
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Invalid Data ID", phosphor::logging::entry("IDINDEX=%x", idIndex));
+        return IPMI_CC_PARM_OUT_OF_RANGE;
+    }
+
+    if (mdrv2->smbiosIsUpdating(idIndex))
+    {
+        if (requestData->xferOffset > UINT_MAX - requestData->xferLength)
+        {
+            phosphor::logging::log<phosphor::logging::level::ERR>(
+                "Offset and length are out of range");
+            return IPMI_CC_PARM_OUT_OF_RANGE;
+        }
+        if (((requestData->xferOffset + requestData->xferLength) >
+             mdrv2->smbiosDir.dir[idIndex].maxDataSize) ||
+            ((requestData->xferOffset + requestData->xferLength) >
+             mdrv2->smbiosDir.dir[idIndex].common.dataSetSize))
+        {
+            phosphor::logging::log<phosphor::logging::level::ERR>(
+                "Send data block Invalid offset/length");
+            return IPMI_CC_REQUEST_DATA_FIELD_LENGTH_LIMIT_EXCEEDED;
+        }
+        if (reinterpret_cast<size_t>(
+                mdrv2->smbiosDir.dir[idIndex].dataStorage) >
+            UINT_MAX - requestData->xferOffset)
+        {
+            phosphor::logging::log<phosphor::logging::level::ERR>(
+                "Offset is out of range");
+            return IPMI_CC_PARM_OUT_OF_RANGE;
+        }
+        uint8_t *destAddr =
+            mdrv2->smbiosDir.dir[idIndex].dataStorage + requestData->xferOffset;
+        uint8_t *sourceAddr = reinterpret_cast<uint8_t *>(mdrv2->area->vPtr);
+        uint32_t calcChecksum =
+            mdrv2->calcChecksum32(sourceAddr, requestData->xferLength);
+        if (calcChecksum != requestData->checksum)
+        {
+            phosphor::logging::log<phosphor::logging::level::ERR>(
+                "Send data block Invalid checksum");
+            return IPMI_CC_OEM_INVALID_CHECKSUM;
+        }
+        else
+        {
+            if (reinterpret_cast<size_t>(sourceAddr) >
+                UINT_MAX - requestData->xferLength)
+            {
+                phosphor::logging::log<phosphor::logging::level::ERR>(
+                    "Length is out of range");
+                return IPMI_CC_PARM_OUT_OF_RANGE;
+            }
+            std::copy(sourceAddr, sourceAddr + requestData->xferLength,
+                      destAddr);
+        }
+    }
+    else
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Send data block failed, other data is updating");
+        return IPMI_CC_DESTINATION_UNAVAILABLE;
+    }
+
+    return IPMI_CC_OK;
+}
+
+bool MDRV2::storeDatatoFlash(MDRSMBIOSHeader *mdrHdr, uint8_t *data)
+{
+    std::ofstream smbiosFile(mdrType2File,
+                             std::ios_base::binary | std::ios_base::trunc);
+    if (!smbiosFile.good())
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Write data from flash error - Open MDRV2 table file failure");
+        return false;
+    }
+
+    try
+    {
+        smbiosFile.write(reinterpret_cast<char *>(mdrHdr),
+                         sizeof(MDRSMBIOSHeader));
+        smbiosFile.write(reinterpret_cast<char *>(data), mdrHdr->dataSize);
+    }
+    catch (std::ofstream::failure &e)
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Write data from flash error - write data error");
+        return false;
+    }
+
+    return true;
+}
+
+void SharedMemoryArea::Initialize(uint32_t addr, uint32_t areaSize)
+{
+    int memDriver = 0;
+
+    // open mem driver for the system memory access
+    memDriver = open("/dev/vgasharedmem", O_RDONLY);
+    if (memDriver < 0)
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Cannot access mem driver");
+        throw std::system_error(EIO, std::generic_category());
+    }
+
+    // map the system memory
+    vPtr = mmap(NULL,                       // where to map to: don't mind
+                areaSize,                   // how many bytes ?
+                PROT_READ,                  // want to read and write
+                MAP_SHARED,                 // no copy on write
+                memDriver,                  // handle to /dev/mem
+                (physicalAddr & pageMask)); // hopefully the Text-buffer :-)
+
+    close(memDriver);
+    if (vPtr == MAP_FAILED)
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Failed to map share memory");
+        throw std::system_error(EIO, std::generic_category());
+    }
+    size = areaSize;
+    physicalAddr = addr;
+}
+
+bool MDRV2::smbiosUnlock(uint8_t index)
+{
+    bool ret;
+    switch (smbiosDir.dir[index].stage)
+    {
+        case MDR2SMBIOSStatusEnum::mdr2Updating:
+            smbiosDir.dir[index].stage = MDR2SMBIOSStatusEnum::mdr2Updated;
+            smbiosDir.dir[index].lock = MDR2DirLockEnum::mdr2DirUnlock;
+
+            timer->stop();
+            smbiosDir.dir[index].lockHandle = 0;
+            ret = true;
+            break;
+
+        case MDR2SMBIOSStatusEnum::mdr2Updated:
+        case MDR2SMBIOSStatusEnum::mdr2Loaded:
+            smbiosDir.dir[index].lock = MDR2DirLockEnum::mdr2DirUnlock;
+
+            timer->stop();
+
+            smbiosDir.dir[index].lockHandle = 0;
+            ret = true;
+            break;
+
+        default:
+            break;
+    }
+
+    return ret;
+}
+
+bool MDRV2::smbiosTryLock(uint8_t flag, uint8_t index, uint16_t *session,
+                          uint16_t timeout)
+{
+    bool ret = false;
+    uint32_t u32Status = 0;
+
+    if (timeout == 0)
+    {
+        timeout = defaultTimeout;
+    }
+    std::chrono::microseconds usec(timeout * sysClock);
+
+    switch (smbiosDir.dir[index].stage)
+    {
+        case MDR2SMBIOSStatusEnum::mdr2Updating:
+            if (smbiosDir.dir[index].lock != MDR2DirLockEnum::mdr2DirLock)
+            {
+                smbiosDir.dir[index].lock = MDR2DirLockEnum::mdr2DirLock;
+                timer->start(usec);
+                lockIndex = index;
+
+                *session = getSessionHandle(&smbiosDir);
+                smbiosDir.dir[index].lockHandle = *session;
+                ret = true;
+            }
+            break;
+        case MDR2SMBIOSStatusEnum::mdr2Init:
+            if (flag)
+            {
+                smbiosDir.dir[index].stage = MDR2SMBIOSStatusEnum::mdr2Updating;
+                smbiosDir.dir[index].lock = MDR2DirLockEnum::mdr2DirUnlock;
+                timer->start(usec);
+                lockIndex = index;
+
+                *session = getSessionHandle(&smbiosDir);
+                smbiosDir.dir[index].lockHandle = *session;
+                ret = true;
+            }
+            break;
+
+        case MDR2SMBIOSStatusEnum::mdr2Updated:
+        case MDR2SMBIOSStatusEnum::mdr2Loaded:
+            if (smbiosDir.dir[index].lock != MDR2DirLockEnum::mdr2DirLock)
+            {
+                if (flag)
+                {
+                    smbiosDir.dir[index].stage =
+                        MDR2SMBIOSStatusEnum::mdr2Updating;
+                    smbiosDir.dir[index].lock = MDR2DirLockEnum::mdr2DirUnlock;
+                }
+                else
+                {
+                    smbiosDir.dir[index].lock = MDR2DirLockEnum::mdr2DirLock;
+                }
+
+                timer->start(usec);
+                lockIndex = index;
+
+                *session = getSessionHandle(&smbiosDir);
+                smbiosDir.dir[index].lockHandle = *session;
+                ret = true;
+            }
+            break;
+
+        default:
+            break;
+    }
+    return ret;
+}
+
+void MDRV2::timeoutHandler()
+{
+    smbiosUnlock(lockIndex);
+    mdrv2->area.reset(nullptr);
+}
+
+ipmi_ret_t cmd_mdr2_lock_data(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+                              ipmi_request_t request, ipmi_response_t response,
+                              ipmi_data_len_t data_len, ipmi_context_t context)
+{
+    auto requestData = reinterpret_cast<const MDRiiLockDataRequest *>(request);
+    auto responseData = reinterpret_cast<MDRiiLockDataResponse *>(response);
+    uint16_t session = 0;
+
+    std::tuple<bool, uint8_t, uint16_t, uint32_t, uint32_t, uint32_t> res;
+
+    if (*data_len < sizeof(MDRiiLockDataRequest))
+    {
+        *data_len = 0;
+        return IPMI_CC_REQ_DATA_LEN_INVALID;
+    }
+
+    *data_len = 0;
+
+    if (mdrv2 == nullptr)
+    {
+        mdrv2 = std::make_unique<MDRV2>();
+    }
+
+    int agentIndex = mdrv2->agentLookup(requestData->agentId);
+    if (agentIndex == -1)
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Unknown agent id",
+            phosphor::logging::entry("ID=%x", requestData->agentId));
+        return IPMI_CC_PARM_OUT_OF_RANGE;
+    }
+
+    std::string service = ipmi::getService(bus, mdrv2Interface, mdrv2Path);
+
+    int idIndex =
+        mdrv2->findDataId(requestData->dataSetInfo.dataInfo,
+                          sizeof(requestData->dataSetInfo.dataInfo), service);
+
+    if ((idIndex < 0) || (idIndex >= maxDirEntries))
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Invalid Data ID", phosphor::logging::entry("IDINDEX=%x", idIndex));
+        return IPMI_CC_PARM_OUT_OF_RANGE;
+    }
+
+    if (!mdrv2->smbiosTryLock(0, idIndex, &session, requestData->timeout))
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Lock Data failed - cannot lock idIndex");
+        return IPMI_CC_PARAMETER_NOT_SUPPORT_IN_PRESENT_STATE;
+    }
+
+    *data_len = sizeof(MDRiiLockDataResponse);
+
+    responseData->mdrVersion = mdr2Version;
+    responseData->lockHandle = session;
+    responseData->dataLength = mdrv2->smbiosDir.dir[idIndex].common.size;
+    responseData->xferAddress = mdrv2->smbiosDir.dir[idIndex].xferBuff;
+    responseData->xferLength = mdrv2->smbiosDir.dir[idIndex].xferSize;
+
+    return IPMI_CC_OK;
+}
+
+ipmi_ret_t cmd_mdr2_unlock_data(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+                                ipmi_request_t request,
+                                ipmi_response_t response,
+                                ipmi_data_len_t data_len,
+                                ipmi_context_t context)
+{
+    phosphor::logging::log<phosphor::logging::level::ERR>("unlock data");
+    auto requestData =
+        reinterpret_cast<const MDRiiUnlockDataRequest *>(request);
+
+    if (*data_len != sizeof(MDRiiUnlockDataRequest))
+    {
+        *data_len = 0;
+        return IPMI_CC_REQ_DATA_LEN_INVALID;
+    }
+
+    *data_len = 0;
+
+    std::string service = ipmi::getService(bus, mdrv2Interface, mdrv2Path);
+
+    if (mdrv2 == nullptr)
+    {
+        mdrv2 = std::make_unique<MDRV2>();
+    }
+
+    int agentIndex = mdrv2->agentLookup(requestData->agentId);
+    if (agentIndex == -1)
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Unknown agent id",
+            phosphor::logging::entry("ID=%x", requestData->agentId));
+        return IPMI_CC_PARM_OUT_OF_RANGE;
+    }
+
+    int idIndex = mdrv2->findLockHandle(requestData->lockHandle);
+
+    if ((idIndex < 0) || (idIndex >= maxDirEntries))
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Invalid Data ID", phosphor::logging::entry("IDINDEX=%x", idIndex));
+        return IPMI_CC_PARM_OUT_OF_RANGE;
+    }
+
+    if (!mdrv2->smbiosUnlock(idIndex))
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Unlock Data failed - cannot unlock idIndex");
+        return IPMI_CC_PARAMETER_NOT_SUPPORT_IN_PRESENT_STATE;
+    }
+
+    return IPMI_CC_OK;
+}
+
+ipmi_ret_t cmd_mdr2_data_start(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+                               ipmi_request_t request, ipmi_response_t response,
+                               ipmi_data_len_t data_len, ipmi_context_t context)
+{
+    auto requestData = reinterpret_cast<const MDRiiDataStartRequest *>(request);
+    auto responseData = reinterpret_cast<MDRiiDataStartResponse *>(response);
+    std::vector<uint8_t> idVector;
+    uint16_t session = 0;
+
+    if (*data_len != sizeof(MDRiiDataStartRequest))
+    {
+        *data_len = 0;
+        return IPMI_CC_REQ_DATA_LEN_INVALID;
+    }
+
+    *data_len = 0;
+
+    if (requestData->dataLength > smbiosTableStorageSize)
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Requested data length is out of SMBIOS Table storage size.");
+        return IPMI_CC_PARM_OUT_OF_RANGE;
+    }
+
+    if ((requestData->xferLength + requestData->xferAddress) > mdriiSMSize)
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Invalid data address and size");
+        return IPMI_CC_PARM_OUT_OF_RANGE;
+    }
+
+    std::string service = ipmi::getService(bus, mdrv2Interface, mdrv2Path);
+
+    if (mdrv2 == nullptr)
+    {
+        mdrv2 = std::make_unique<MDRV2>();
+    }
+
+    int agentIndex = mdrv2->agentLookup(requestData->agentId);
+    if (agentIndex == -1)
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Unknown agent id",
+            phosphor::logging::entry("ID=%x", requestData->agentId));
+        return IPMI_CC_PARM_OUT_OF_RANGE;
+    }
+
+    int idIndex =
+        mdrv2->findDataId(requestData->dataSetInfo.dataInfo,
+                          sizeof(requestData->dataSetInfo.dataInfo), service);
+
+    if ((idIndex < 0) || (idIndex >= maxDirEntries))
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Invalid Data ID", phosphor::logging::entry("IDINDEX=%x", idIndex));
+        return IPMI_CC_PARM_OUT_OF_RANGE;
+    }
+
+    if (mdrv2->smbiosTryLock(1, idIndex, &session, requestData->timeout))
+    {
+        try
+        {
+            mdrv2->area = std::make_unique<SharedMemoryArea>(
+                requestData->xferAddress, requestData->xferLength);
+        }
+        catch (const std::system_error &e)
+        {
+            mdrv2->smbiosUnlock(idIndex);
+            phosphor::logging::log<phosphor::logging::level::ERR>(
+                "Unable to access share memory");
+            return IPMI_CC_UNSPECIFIED_ERROR;
+        }
+        mdrv2->smbiosDir.dir[idIndex].common.size = requestData->dataLength;
+        mdrv2->smbiosDir.dir[idIndex].lockHandle = session;
+        if (-1 ==
+            mdrv2->syncDirCommonData(
+                idIndex, mdrv2->smbiosDir.dir[idIndex].common.size, service))
+        {
+            phosphor::logging::log<phosphor::logging::level::ERR>(
+                "Unable to sync data to service");
+            return IPMI_CC_RESPONSE_ERROR;
+        }
+    }
+    else
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Canot lock smbios");
+        return IPMI_CC_UNSPECIFIED_ERROR;
+    }
+
+    responseData->sessionHandle = session;
+    responseData->xferStartAck = 1;
+
+    *data_len = sizeof(MDRiiDataStartResponse);
+    return IPMI_CC_OK;
+}
+
+ipmi_ret_t cmd_mdr2_data_done(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+                              ipmi_request_t request, ipmi_response_t response,
+                              ipmi_data_len_t data_len, ipmi_context_t context)
+{
+    auto requestData = reinterpret_cast<const MDRiiDataDoneRequest *>(request);
+
+    if (*data_len != sizeof(MDRiiDataDoneRequest))
+    {
+        *data_len = 0;
+        return IPMI_CC_REQ_DATA_LEN_INVALID;
+    }
+
+    *data_len = 0;
+
+    if (mdrv2 == nullptr)
+    {
+        mdrv2 = std::make_unique<MDRV2>();
+    }
+
+    int agentIndex = mdrv2->agentLookup(requestData->agentId);
+    if (agentIndex == -1)
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Unknown agent id",
+            phosphor::logging::entry("ID=%x", requestData->agentId));
+        return IPMI_CC_PARM_OUT_OF_RANGE;
+    }
+
+    int idIndex = mdrv2->findLockHandle(requestData->lockHandle);
+
+    if ((idIndex < 0) || (idIndex >= maxDirEntries))
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Invalid Data ID", phosphor::logging::entry("IDINDEX=%x", idIndex));
+        return IPMI_CC_PARM_OUT_OF_RANGE;
+    }
+
+    if (!mdrv2->smbiosUnlock(idIndex))
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Send data done failed - cannot unlock idIndex");
+        return IPMI_CC_DESTINATION_UNAVAILABLE;
+    }
+
+    mdrv2->area.reset(nullptr);
+    MDRSMBIOSHeader mdr2Smbios;
+    mdr2Smbios.mdrType = mdrTypeII;
+    mdr2Smbios.dirVer = mdrv2->smbiosDir.dir[0].common.dataVersion;
+    mdr2Smbios.timestamp = mdrv2->smbiosDir.dir[0].common.timestamp;
+    mdr2Smbios.dataSize = mdrv2->smbiosDir.dir[0].common.size;
+
+    if (access(smbiosPath, 0) == -1)
+    {
+        int flag = mkdir(smbiosPath, S_IRWXU);
+        if (flag != 0)
+        {
+            phosphor::logging::log<phosphor::logging::level::ERR>(
+                "create folder failed for writting smbios file");
+        }
+    }
+    if (!mdrv2->storeDatatoFlash(
+            &mdr2Smbios, mdrv2->smbiosDir.dir[smbiosDirIndex].dataStorage))
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "MDR2 Store data to flash failed");
+        return IPMI_CC_DESTINATION_UNAVAILABLE;
+    }
+
+    bool status = false;
+    std::string service = ipmi::getService(bus, mdrv2Interface, mdrv2Path);
+    sdbusplus::message::message method = bus.new_method_call(
+        service.c_str(), mdrv2Path, mdrv2Interface, "AgentSynchronizeData");
+
+    try
+    {
+        sdbusplus::message::message reply = bus.call(method);
+        reply.read(status);
+    }
+    catch (sdbusplus::exception_t &)
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Error Sync data with service",
+            phosphor::logging::entry("SERVICE=%s", service.c_str()),
+            phosphor::logging::entry("PATH=%s", mdrv2Path));
+        return IPMI_CC_RESPONSE_ERROR;
+    }
+
+    if (!status)
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Sync data with service failure");
+        return IPMI_CC_UNSPECIFIED_ERROR;
+    }
+
+    return IPMI_CC_OK;
+}
+
+static void register_netfn_smbiosmdrv2_functions(void)
+{
+    // MDR V2 Command
+    // <Get MDRII Status Command>
+    ipmi_register_callback(NETFUN_INTEL_APP_OEM,
+                           IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_AGENT_STATUS,
+                           NULL, cmd_mdr2_agent_status, PRIVILEGE_OPERATOR);
+
+    // <Get MDRII Directory Command>
+    ipmi_register_callback(NETFUN_INTEL_APP_OEM,
+                           IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_GET_DIR, NULL,
+                           cmd_mdr2_get_dir, PRIVILEGE_OPERATOR);
+
+    // <Send MDRII Directory Command>
+    ipmi_register_callback(NETFUN_INTEL_APP_OEM,
+                           IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_SEND_DIR, NULL,
+                           cmd_mdr2_send_dir, PRIVILEGE_OPERATOR);
+
+    // <Get MDRII Data Info Command>
+    ipmi_register_callback(NETFUN_INTEL_APP_OEM,
+                           IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_GET_DATA_INFO,
+                           NULL, cmd_mdr2_get_data_info, PRIVILEGE_OPERATOR);
+
+    // <Send MDRII Info Offer>
+    ipmi_register_callback(
+        NETFUN_INTEL_APP_OEM,
+        IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_SEND_DATA_INFO_OFFER, NULL,
+        cmd_mdr2_data_info_offer, PRIVILEGE_OPERATOR);
+
+    // <Send MDRII Data Info>
+    ipmi_register_callback(NETFUN_INTEL_APP_OEM,
+                           IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_SEND_DATA_INFO,
+                           NULL, cmd_mdr2_send_data_info, PRIVILEGE_OPERATOR);
+
+    // <Get MDRII Data Block Command>
+    ipmi_register_callback(NETFUN_INTEL_APP_OEM,
+                           IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_GET_DATA_BLOCK,
+                           NULL, cmd_mdr2_get_data_block, PRIVILEGE_OPERATOR);
+
+    // <Send MDRII Data Block>
+    ipmi_register_callback(NETFUN_INTEL_APP_OEM,
+                           IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_SEND_DATA_BLOCK,
+                           NULL, cmd_mdr2_send_data_block, PRIVILEGE_OPERATOR);
+
+    // <Lock MDRII Data Command>
+    ipmi_register_callback(NETFUN_INTEL_APP_OEM,
+                           IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_LOCK_DATA, NULL,
+                           cmd_mdr2_lock_data, PRIVILEGE_OPERATOR);
+
+    // <Unlock MDRII Data Command>
+    ipmi_register_callback(NETFUN_INTEL_APP_OEM,
+                           IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_UNLOCK_DATA,
+                           NULL, cmd_mdr2_unlock_data, PRIVILEGE_OPERATOR);
+
+    // <Send MDRII Data Start>
+    ipmi_register_callback(NETFUN_INTEL_APP_OEM,
+                           IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_DATA_START, NULL,
+                           cmd_mdr2_data_start, PRIVILEGE_OPERATOR);
+
+    // <Send MDRII Data Done>
+    ipmi_register_callback(NETFUN_INTEL_APP_OEM,
+                           IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_DATA_DONE, NULL,
+                           cmd_mdr2_data_done, PRIVILEGE_OPERATOR);
+}