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/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