summaryrefslogtreecommitdiff
path: root/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi
diff options
context:
space:
mode:
Diffstat (limited to 'meta-openbmc-mods/meta-common/recipes-phosphor/ipmi')
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-config.bbappend21
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-config/channel_access.json23
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-config/channel_config.json178
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-config/dev_id.json2
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-config/master_write_read_white_list.json76
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-fru-merge-config-native.bbappend8
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-fru-merge-config-native/config.yaml31
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0009-IPv6-Network-changes.patch877
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0010-fix-get-system-GUID-ipmi-command.patch36
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0013-ipmi-add-set-bios-id-to-whitelist.patch22
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0039-ipmi-add-oem-command-get-AIC-FRU-to-whitelist.patch25
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0050-enable-6-oem-commands.patch15
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0053-Fix-keep-looping-issue-when-entering-OS.patch80
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0054-Fix-User-commands-require-channel-layer-lib.patch37
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0056-add-SetInProgress-to-get-set-boot-option-cmd.patch102
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0057-Add-timer-use-actions-support.patch31
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0059-Move-Set-SOL-config-parameter-to-host-ipmid.patch383
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0060-Move-Get-SOL-config-parameter-to-host-ipmid.patch260
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0062-Update-IPMI-Chassis-Control-command.patch289
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0063-Save-the-pre-timeout-interrupt-in-dbus-property.patch140
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0064-Enable-watchdog-to-save-useflag-after-host-power-off.patch66
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0064-Update-provisioning-mode-filter-logic.patch286
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/host-ipmid-whitelist.conf196
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/phosphor-ipmi-host.service28
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host_%.bbappend45
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-ipmb_%.bbappend2
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-kcs/99-ipmi-kcs.rules2
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-kcs_%.bbappend21
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-net/00010-Change-Authentication-Parameter.patch40
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-net/0006-Modify-dbus-namespace-of-chassis-control-for-guid.patch39
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-net/0009-Add-dbus-interface-for-sol-commands.patch319
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-net/0011-Remove-Get-SOL-Config-Command-from-Netipmid.patch336
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-net_%.bbappend26
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-sensor-inventory%.bbappend1
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-sensor-inventory%/config.yaml0
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-node-manager-proxy_git.bb19
36 files changed, 4062 insertions, 0 deletions
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-config.bbappend b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-config.bbappend
new file mode 100644
index 000000000..616fb9a75
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-config.bbappend
@@ -0,0 +1,21 @@
+FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
+SRC_URI += " file://dev_id.json \
+ file://channel_access.json \
+ file://channel_config.json \
+ file://master_write_read_white_list.json \
+ "
+
+FILES_${PN} += " \
+ ${datadir}/ipmi-providers/channel_access.json \
+ ${datadir}/ipmi-providers/channel_config.json \
+ ${datadir}/ipmi-providers/master_write_read_white_list.json \
+ "
+
+do_install_append() {
+ install -m 0644 -D ${WORKDIR}/channel_access.json \
+ ${D}${datadir}/ipmi-providers/channel_access.json
+ install -m 0644 -D ${WORKDIR}/channel_config.json \
+ ${D}${datadir}/ipmi-providers/channel_config.json
+ install -m 0644 -D ${WORKDIR}/master_write_read_white_list.json \
+ ${D}${datadir}/ipmi-providers/master_write_read_white_list.json
+}
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-config/channel_access.json b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-config/channel_access.json
new file mode 100644
index 000000000..299483121
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-config/channel_access.json
@@ -0,0 +1,23 @@
+{
+ "1" : {
+ "access_mode" : "always_available",
+ "user_auth_disabled" : false,
+ "per_msg_auth_disabled" : false,
+ "alerting_disabled" : false,
+ "priv_limit" : "priv-admin"
+ },
+ "2" : {
+ "access_mode" : "always_available",
+ "user_auth_disabled" : false,
+ "per_msg_auth_disabled" : false,
+ "alerting_disabled" : false,
+ "priv_limit" : "priv-admin"
+ },
+ "3" : {
+ "access_mode" : "always_available",
+ "user_auth_disabled" : false,
+ "per_msg_auth_disabled" : false,
+ "alerting_disabled" : false,
+ "priv_limit" : "priv-admin"
+ }
+}
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-config/channel_config.json b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-config/channel_config.json
new file mode 100644
index 000000000..dc9c2ce20
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-config/channel_config.json
@@ -0,0 +1,178 @@
+{
+ "0" : {
+ "name" : "IPMB",
+ "is_valid" : true,
+ "active_sessions" : 0,
+ "channel_info" : {
+ "medium_type" : "ipmb",
+ "protocol_type" : "ipmb-1.0",
+ "session_supported" : "session-less",
+ "is_ipmi" : true
+ }
+ },
+ "1" : {
+ "name" : "eth1",
+ "is_valid" : true,
+ "active_sessions" : 0,
+ "channel_info" : {
+ "medium_type" : "lan-802.3",
+ "protocol_type" : "ipmb-1.0",
+ "session_supported" : "multi-session",
+ "is_ipmi" : true
+ }
+ },
+ "2" : {
+ "name" : "RESERVED",
+ "is_valid" : false,
+ "active_sessions" : 0,
+ "channel_info" : {
+ "medium_type" : "reserved",
+ "protocol_type" : "na",
+ "session_supported" : "session-less",
+ "is_ipmi" : true
+ }
+ },
+ "3" : {
+ "name" : "eth0",
+ "is_valid" : true,
+ "active_sessions" : 0,
+ "channel_info" : {
+ "medium_type" : "lan-802.3",
+ "protocol_type" : "ipmb-1.0",
+ "session_supported" : "multi-session",
+ "is_ipmi" : true
+ }
+ },
+ "4" : {
+ "name" : "RESERVED",
+ "is_valid" : true,
+ "active_sessions" : 0,
+ "channel_info" : {
+ "medium_type" : "reserved",
+ "protocol_type" : "na",
+ "session_supported" : "session-less",
+ "is_ipmi" : true
+ }
+ },
+ "5" : {
+ "name" : "RESERVED",
+ "is_valid" : false,
+ "active_sessions" : 0,
+ "channel_info" : {
+ "medium_type" : "reserved",
+ "protocol_type" : "na",
+ "session_supported" : "session-less",
+ "is_ipmi" : true
+ }
+ },
+ "6" : {
+ "name" : "SMLINK",
+ "is_valid" : true,
+ "active_sessions" : 0,
+ "channel_info" : {
+ "medium_type" : "ipmb",
+ "protocol_type" : "ipmb-1.0",
+ "session_supported" : "session-less",
+ "is_ipmi" : true
+ }
+ },
+ "7" : {
+ "name" : "ipmi_kcs4",
+ "is_valid" : true,
+ "active_sessions" : 0,
+ "channel_info" : {
+ "medium_type" : "system-interface",
+ "protocol_type" : "kcs",
+ "session_supported" : "session-less",
+ "is_ipmi" : true
+ }
+ },
+ "8" : {
+ "name" : "INTRABMC",
+ "is_valid" : true,
+ "active_sessions" : 0,
+ "channel_info" : {
+ "medium_type" : "oem",
+ "protocol_type" : "oem",
+ "session_supported" : "session-less",
+ "is_ipmi" : true
+ }
+ },
+ "9" : {
+ "name" : "SIPMB",
+ "is_valid" : true,
+ "active_sessions" : 0,
+ "channel_info" : {
+ "medium_type" : "ipmb",
+ "protocol_type" : "ipmb-1.0",
+ "session_supported" : "session-less",
+ "is_ipmi" : true
+ }
+ },
+ "10" : {
+ "name" : "PCIE",
+ "is_valid" : true,
+ "active_sessions" : 0,
+ "channel_info" : {
+ "medium_type" : "ipmb",
+ "protocol_type" : "ipmb-1.0",
+ "session_supported" : "session-less",
+ "is_ipmi" : true
+ }
+ },
+ "11" : {
+ "name" : "RESERVED",
+ "is_valid" : false,
+ "active_sessions" : 0,
+ "channel_info" : {
+ "medium_type" : "reserved",
+ "protocol_type" : "na",
+ "session_supported" : "session-less",
+ "is_ipmi" : true
+ }
+ },
+ "12" : {
+ "name" : "INTERNAL",
+ "is_valid" : false,
+ "active_sessions" : 0,
+ "channel_info" : {
+ "medium_type" : "ipmb",
+ "protocol_type" : "ipmb-1.0",
+ "session_supported" : "session-less",
+ "is_ipmi" : true
+ }
+ },
+ "13" : {
+ "name" : "RESERVED",
+ "is_valid" : false,
+ "active_sessions" : 0,
+ "channel_info" : {
+ "medium_type" : "reserved",
+ "protocol_type" : "na",
+ "session_supported" : "session-less",
+ "is_ipmi" : true
+ }
+ },
+ "14" : {
+ "name" : "SELF",
+ "is_valid" : false,
+ "active_sessions" : 0,
+ "channel_info" : {
+ "medium_type" : "unknown",
+ "protocol_type" : "na",
+ "session_supported" : "session-less",
+ "is_ipmi" : true
+ }
+ },
+ "15" : {
+ "name" : "ipmi_kcs3",
+ "is_valid" : true,
+ "active_sessions" : 0,
+ "channel_info" : {
+ "medium_type" : "system-interface",
+ "protocol_type" : "kcs",
+ "session_supported" : "session-less",
+ "is_ipmi" : true
+ }
+ }
+}
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-config/dev_id.json b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-config/dev_id.json
new file mode 100644
index 000000000..e561569d9
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-config/dev_id.json
@@ -0,0 +1,2 @@
+{"id": 35, "revision": 0, "addn_dev_support": 191,
+ "manuf_id": 343, "prod_id": 123, "aux": 0}
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-config/master_write_read_white_list.json b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-config/master_write_read_white_list.json
new file mode 100644
index 000000000..6fc46f452
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-config/master_write_read_white_list.json
@@ -0,0 +1,76 @@
+{
+ "filters": [
+ {
+ "Description": "Allow full read - ignore first byte write value",
+ "busId": "0x01",
+ "slaveAddr": "0x4d",
+ "slaveAddrMask": "0x00",
+ "command": "0x00",
+ "commandMask": "0xFF"
+ },
+ {
+ "Description": "Allow full read - ignore first byte write value",
+ "busId": "0x01",
+ "slaveAddr": "0x57",
+ "slaveAddrMask": "0x00",
+ "command": "0x00",
+ "commandMask": "0xFF"
+ },
+ {
+ "Description": "Allow full read - ignore first byte write value",
+ "busId": "0x02",
+ "slaveAddr": "0x40",
+ "slaveAddrMask": "0x00",
+ "command": "0x00",
+ "commandMask": "0xFF"
+ },
+ {
+ "Description": "Allow full read - ignore first byte write value",
+ "busId": "0x02",
+ "slaveAddr": "0x49",
+ "slaveAddrMask": "0x00",
+ "command": "0x00",
+ "commandMask": "0xFF"
+ },
+ {
+ "Description": "Allow full read - ignore first byte write value",
+ "busId": "0x02",
+ "slaveAddr": "0x51",
+ "slaveAddrMask": "0x00",
+ "command": "0x00",
+ "commandMask": "0xFF"
+ },
+ {
+ "Description": "Allow full read - ignore first byte write value",
+ "busId": "0x03",
+ "slaveAddr": "0x44",
+ "slaveAddrMask": "0x00",
+ "command": "0x00",
+ "commandMask": "0xFF"
+ },
+ {
+ "Description": "Allow full read - ignore first byte write value",
+ "busId": "0x03",
+ "slaveAddr": "0x68",
+ "slaveAddrMask": "0x00",
+ "command": "0x00",
+ "commandMask": "0xFF"
+ },
+ {
+ "Description": "Allow full read - ignore first byte write value",
+ "busId": "0x06",
+ "slaveAddr": "0x40",
+ "slaveAddrMask": "0x00",
+ "command": "0x00",
+ "commandMask": "0xFF"
+ },
+ {
+ "Description": "Allow full read - ignore first byte write value",
+ "busId": "0x07",
+ "slaveAddr": "0x51",
+ "slaveAddrMask": "0x00",
+ "command": "0x00",
+ "commandMask": "0xFF"
+ }
+ ]
+}
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-fru-merge-config-native.bbappend b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-fru-merge-config-native.bbappend
new file mode 100644
index 000000000..2d892ad1a
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-fru-merge-config-native.bbappend
@@ -0,0 +1,8 @@
+FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
+SRC_URI += " file://config.yaml"
+
+#override source file before it is used for final FRU file (merged from multiple sources)
+do_install() {
+ cp ${WORKDIR}/config.yaml ${config_datadir}/
+}
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-fru-merge-config-native/config.yaml b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-fru-merge-config-native/config.yaml
new file mode 100644
index 000000000..e9b7a621e
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-fru-merge-config-native/config.yaml
@@ -0,0 +1,31 @@
+# A YAML similar to this example would have to be generated, for eg with MRW
+# inputs and system configuration, to depict IPMI Fru information.
+#
+# This file maps IPMI properties to phosphor dbus inventory properties
+#
+# This YAML could help generate C++ code.
+# Format of the YAML:
+# Fruid:
+# Associated Fru paths
+# d-bus Interfaces
+# d-bus Properties
+# IPMI Fru mapping
+0:
+ /system/board/WFP_Baseboard:
+ entityID: 23
+ entityInstance: 1
+ interfaces:
+ xyz.openbmc_project.Inventory.Item:
+ name:
+ IPMIFruProperty: Product Name
+ IPMIFruSection: Product
+ xyz.openbmc_project.Inventory.Decorator.Asset:
+ Manufacturer:
+ IPMIFruProperty: Manufacturer
+ IPMIFruSection: Product
+ PartNumber:
+ IPMIFruProperty: Part Number
+ IPMIFruSection: Product
+ SerialNumber:
+ IPMIFruProperty: Serial Number
+ IPMIFruSection: Product
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0009-IPv6-Network-changes.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0009-IPv6-Network-changes.patch
new file mode 100644
index 000000000..c862a306a
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0009-IPv6-Network-changes.patch
@@ -0,0 +1,877 @@
+From c20bc8eb6a08d177d951012eb91b37398b15d81d Mon Sep 17 00:00:00 2001
+From: Vernon Mauery <vernon.mauery@linux.intel.com>
+Date: Tue, 27 Nov 2018 11:01:15 -0800
+Subject: [PATCH] IPv6 Network changes
+
+Allow IPv6 IPMI set/get commands
+
+Signed-off-by: David Cobbley <david.j.cobbley@linux.intel.com>
+Signed-off-by: Yong Li <yong.b.li@linux.intel.com>
+Signed-off-by: Vernon Mauery <vernon.mauery@linux.intel.com>
+
+Change-Id: If5528d3b7294c5f8c17db5919439235d0fad0446
+---
+ include/ipmid/types.hpp | 9 +
+ include/ipmid/utils.hpp | 1 +
+ transporthandler.cpp | 654 +++++++++++++++++++++++++++++++++++++++-
+ transporthandler.hpp | 50 +++
+ 4 files changed, 713 insertions(+), 1 deletion(-)
+
+Index: phosphor-host-ipmid.clean/include/ipmid/types.hpp
+===================================================================
+--- phosphor-host-ipmid.clean.orig/include/ipmid/types.hpp
++++ phosphor-host-ipmid.clean/include/ipmid/types.hpp
+@@ -224,6 +224,7 @@ constexpr auto ADDR_TYPE_FORMAT = "%hhx"
+
+ constexpr auto IPV4_ADDRESS_SIZE_BYTE = 4;
+ constexpr auto IPV6_ADDRESS_SIZE_BYTE = 16;
++constexpr auto IPV6_ADDRESS_STATUS_SIZE = 22;
+
+ constexpr auto DEFAULT_MAC_ADDRESS = "00:00:00:00:00:00";
+ constexpr auto DEFAULT_ADDRESS = "0.0.0.0";
+@@ -235,6 +236,7 @@ constexpr auto BITS_32 = 32;
+ constexpr auto MASK_32_BIT = 0xFFFFFFFF;
+ constexpr auto VLAN_ID_MASK = 0x00000FFF;
+ constexpr auto VLAN_ENABLE_MASK = 0x8000;
++constexpr auto IPV6_DUID_SIZE = 18;
+
+ enum class IPOrigin : uint8_t
+ {
+@@ -243,5 +245,12 @@ enum class IPOrigin : uint8_t
+ DHCP = 2,
+ };
+
++enum class AddressingEnables : uint8_t
++{
++ IPv4Only = 0,
++ IPv6Only = 1,
++ IPv4AndIPv6 = 2,
++};
++
+ } // namespace network
+ } // namespace ipmi
+Index: phosphor-host-ipmid.clean/include/ipmid/utils.hpp
+===================================================================
+--- phosphor-host-ipmid.clean.orig/include/ipmid/utils.hpp
++++ phosphor-host-ipmid.clean/include/ipmid/utils.hpp
+@@ -256,6 +256,7 @@ namespace network
+ constexpr auto ROOT = "/xyz/openbmc_project/network";
+ constexpr auto SERVICE = "xyz.openbmc_project.Network";
+ constexpr auto IP_TYPE = "ipv4";
++constexpr auto IPV6_TYPE = "ipv6";
+ constexpr auto IPV4_PREFIX = "169.254";
+ constexpr auto IPV6_PREFIX = "fe80";
+ constexpr auto IP_INTERFACE = "xyz.openbmc_project.Network.IP";
+Index: phosphor-host-ipmid.clean/transporthandler.cpp
+===================================================================
+--- phosphor-host-ipmid.clean.orig/transporthandler.cpp
++++ phosphor-host-ipmid.clean/transporthandler.cpp
+@@ -29,6 +29,12 @@ std::unique_ptr<phosphor::Timer> network
+
+ const int SIZE_MAC = 18; // xx:xx:xx:xx:xx:xx
+ constexpr auto ipv4Protocol = "xyz.openbmc_project.Network.IP.Protocol.IPv4";
++constexpr auto ipv6Protocol = "xyz.openbmc_project.Network.IP.Protocol.IPv6";
++
++static const std::array<std::string, 3> ipAddressEnablesType = {
++ "xyz.openbmc_project.Network.EthernetInterface.IPAllowed.IPv4Only",
++ "xyz.openbmc_project.Network.EthernetInterface.IPAllowed.IPv6Only",
++ "xyz.openbmc_project.Network.EthernetInterface.IPAllowed.IPv4AndIPv6"};
+
+ std::map<int, std::unique_ptr<struct ChannelConfig_t>> channelConfig;
+
+@@ -445,6 +451,11 @@ ipmi_ret_t ipmi_transport_set_lan(ipmi_n
+ {
+ case LanParam::IP:
+ {
++ if (reqLen != lanParamIPSize)
++ {
++ return IPMI_CC_REQ_DATA_LEN_INVALID;
++ }
++
+ std::snprintf(ipaddr, INET_ADDRSTRLEN,
+ ipmi::network::IP_ADDRESS_FORMAT, reqptr->data[0],
+ reqptr->data[1], reqptr->data[2], reqptr->data[3]);
+@@ -455,6 +466,11 @@ ipmi_ret_t ipmi_transport_set_lan(ipmi_n
+
+ case LanParam::IPSRC:
+ {
++ if (reqLen != lanParamIPSrcSize)
++ {
++ return IPMI_CC_REQ_DATA_LEN_INVALID;
++ }
++
+ uint8_t ipsrc{};
+ std::memcpy(&ipsrc, reqptr->data, ipmi::network::IPSRC_SIZE_BYTE);
+ channelConf->ipsrc = static_cast<ipmi::network::IPOrigin>(ipsrc);
+@@ -463,6 +479,11 @@ ipmi_ret_t ipmi_transport_set_lan(ipmi_n
+
+ case LanParam::MAC:
+ {
++ if (reqLen != lanParamMACSize)
++ {
++ return IPMI_CC_REQ_DATA_LEN_INVALID;
++ }
++
+ char mac[SIZE_MAC];
+
+ std::snprintf(mac, SIZE_MAC, ipmi::network::MAC_ADDRESS_FORMAT,
+@@ -483,6 +504,11 @@ ipmi_ret_t ipmi_transport_set_lan(ipmi_n
+
+ case LanParam::SUBNET:
+ {
++ if (reqLen != lanParamSubnetSize)
++ {
++ return IPMI_CC_REQ_DATA_LEN_INVALID;
++ }
++
+ std::snprintf(netmask, INET_ADDRSTRLEN,
+ ipmi::network::IP_ADDRESS_FORMAT, reqptr->data[0],
+ reqptr->data[1], reqptr->data[2], reqptr->data[3]);
+@@ -492,6 +518,11 @@ ipmi_ret_t ipmi_transport_set_lan(ipmi_n
+
+ case LanParam::GATEWAY:
+ {
++ if (reqLen != lanParamGatewaySize)
++ {
++ return IPMI_CC_REQ_DATA_LEN_INVALID;
++ }
++
+ std::snprintf(gateway, INET_ADDRSTRLEN,
+ ipmi::network::IP_ADDRESS_FORMAT, reqptr->data[0],
+ reqptr->data[1], reqptr->data[2], reqptr->data[3]);
+@@ -522,6 +553,11 @@ ipmi_ret_t ipmi_transport_set_lan(ipmi_n
+
+ case LanParam::INPROGRESS:
+ {
++ if (reqLen != lanParamInProgressSize)
++ {
++ return IPMI_CC_REQ_DATA_LEN_INVALID;
++ }
++
+ if (reqptr->data[0] == SET_COMPLETE)
+ {
+ channelConf->lan_set_in_progress = SET_COMPLETE;
+@@ -540,6 +576,122 @@ ipmi_ret_t ipmi_transport_set_lan(ipmi_n
+ }
+ break;
+
++ case LanParam::IPV6_AND_IPV4_ENABLES:
++ {
++ if (reqLen != lanParamIPv6AndIPv4EnablesSize)
++ {
++ return IPMI_CC_REQ_DATA_LEN_INVALID;
++ }
++
++ channelConf->ipv6AddressingEnables = reqptr->data[0];
++ break;
++ }
++
++ case LanParam::IPV6_STATIC_ADDRESSES:
++ {
++ if (reqLen != lanParamIPv6StaticAddressesSize)
++ {
++ return IPMI_CC_REQ_DATA_LEN_INVALID;
++ }
++
++ channelConf->ipv6AddressSource =
++ reqptr->data[1] & 0x81; // Looking at bit 0 and bit 7
++ char tmpIPV6[INET6_ADDRSTRLEN];
++ inet_ntop(AF_INET6, &reqptr->data[2], tmpIPV6, INET6_ADDRSTRLEN);
++ channelConf->ipv6Addr.assign(tmpIPV6);
++ channelConf->ipv6Prefix = reqptr->data[19];
++ break;
++ }
++
++ case LanParam::IPV6_ROUTER_ADDRESS_CONF_CTRL:
++ {
++ if (reqLen != lanParamIPv6RouterAddressConfCtrlSize)
++ {
++ return IPMI_CC_REQ_DATA_LEN_INVALID;
++ }
++
++ channelConf->ipv6RouterAddressConfigControl = reqptr->data[0];
++ break;
++ }
++
++ case LanParam::IPV6_STATIC_ROUTER_1_IP_ADDR:
++ {
++ if (reqLen != lanParamIPv6StaticRouter1IPAddrSize)
++ {
++ return IPMI_CC_REQ_DATA_LEN_INVALID;
++ }
++
++ char tmpIPV6[INET6_ADDRSTRLEN];
++ inet_ntop(AF_INET6, reinterpret_cast<const void*>(reqptr->data),
++ tmpIPV6, INET6_ADDRSTRLEN);
++ channelConf->ipv6GatewayAddr.assign(tmpIPV6);
++ break;
++ }
++
++ case LanParam::IPV6_STATIC_ROUTER_1_PREFIX_LEN:
++ {
++ if (reqLen != lanParamIPv6StaticRouter1PrefixLenSize)
++ {
++ return IPMI_CC_REQ_DATA_LEN_INVALID;
++ }
++
++ channelConf->ipv6GatewayPrefixLength = reqptr->data[0];
++ break;
++ }
++
++ case LanParam::IPV6_STATIC_ROUTER_1_PREFIX_VAL:
++ {
++ if (reqLen != lanParamIPv6StaticRouter1PrefixValSize)
++ {
++ return IPMI_CC_REQ_DATA_LEN_INVALID;
++ }
++
++ char tmpIPV6[INET6_ADDRSTRLEN];
++ inet_ntop(AF_INET6, reinterpret_cast<const void*>(reqptr->data),
++ tmpIPV6, INET6_ADDRSTRLEN);
++ channelConf->ipv6GatewayPrefixValue.assign(tmpIPV6);
++ break;
++ }
++
++ case LanParam::IPV6_STATIC_ROUTER_2_IP_ADDR:
++ {
++ if (reqLen != lanParamIPv6StaticRouter2IPAddrSize)
++ {
++ return IPMI_CC_REQ_DATA_LEN_INVALID;
++ }
++
++ char tmpIPV6[INET6_ADDRSTRLEN];
++ inet_ntop(AF_INET6, reinterpret_cast<const void*>(reqptr->data),
++ tmpIPV6, INET6_ADDRSTRLEN);
++ channelConf->ipv6BackupGatewayAddr.assign(tmpIPV6);
++ break;
++ }
++
++ case LanParam::IPV6_STATIC_ROUTER_2_PREFIX_LEN:
++ {
++ if (reqLen != lanParamIPv6StaticRouter2PrefixLenSize)
++ {
++ return IPMI_CC_REQ_DATA_LEN_INVALID;
++ }
++
++ channelConf->ipv6BackupGatewayPrefixLength = reqptr->data[0];
++ break;
++ }
++
++ case LanParam::IPV6_STATIC_ROUTER_2_PREFIX_VAL:
++ {
++ if (reqLen != lanParamIPv6StaticRouter2PrefixValSize)
++ {
++ return IPMI_CC_REQ_DATA_LEN_INVALID;
++ }
++
++ char tmpIPV6[INET6_ADDRSTRLEN];
++ inet_ntop(AF_INET6, reinterpret_cast<const void*>(reqptr->data),
++ tmpIPV6, INET6_ADDRSTRLEN);
++ channelConf->ipv6BackupGatewayPrefixValue.assign(tmpIPV6);
++ break;
++ }
++
+ default:
+ {
+ rc = IPMI_CC_PARM_NOT_SUPPORTED;
+@@ -568,6 +720,7 @@ ipmi_ret_t ipmi_transport_get_lan(ipmi_n
+ ipmi_ret_t rc = IPMI_CC_OK;
+ *data_len = 0;
+ const uint8_t current_revision = 0x11; // Current rev per IPMI Spec 2.0
++ sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
+
+ get_lan_t* reqptr = (get_lan_t*)request;
+ // channel number is the lower nibble
+@@ -713,6 +866,476 @@ ipmi_ret_t ipmi_transport_get_lan(ipmi_n
+ static_cast<uint8_t>(cipherList.size());
+ break;
+ }
++ case LanParam::IPV6_AND_IPV4_SUPPORTED:
++ {
++ uint8_t addressSupport =
++ 0x1; // Allow both IPv4 & IPv6 simultaneously
++ std::array<uint8_t, 2> buf = {current_revision, addressSupport};
++ std::copy(buf.begin(), buf.end(), static_cast<uint8_t*>(response));
++ *data_len = buf.size();
++ break;
++ }
++ case LanParam::IPV6_AND_IPV4_ENABLES:
++ {
++ // If DHCP, check if you have an ipv6 and ipv4 address. If static
++ // return not supported
++
++ // 00h check if conf DHCP == ipv4 or off
++ // 01h check if conf DHCP == ipv6
++ // 02h check if DHCP == true
++
++ auto ethIP = ethdevice + "/" + ipmi::network::IPV6_TYPE;
++ std::string networkInterfacePath;
++ uint8_t ipVAddressEnables = 0;
++
++ if (channelConf->lan_set_in_progress == SET_COMPLETE)
++ {
++ try
++ {
++ ipmi::ObjectTree ancestorMap;
++ // if the system has an ip object,then
++ // get the IP object.
++ auto ipObject =
++ ipmi::getDbusObject(bus, ipmi::network::IP_INTERFACE,
++ ipmi::network::ROOT, ethIP);
++ // Get the parent interface of the IP object.
++ try
++ {
++ ipmi::InterfaceList interfaces;
++ interfaces.emplace_back(
++ ipmi::network::ETHERNET_INTERFACE);
++
++ ancestorMap = ipmi::getAllAncestors(
++ bus, ipObject.first, std::move(interfaces));
++ }
++ catch (InternalFailure& e)
++ {
++ // if unable to get the parent interface
++ // then commit the error and return.
++ log<level::ERR>(
++ "Unable to get the parent interface",
++ entry("PATH=%s", ipObject.first.c_str()),
++ entry("INTERFACE=%s",
++ ipmi::network::ETHERNET_INTERFACE));
++ return IPMI_CC_UNSPECIFIED_ERROR;
++ }
++ // for an ip object there would be single parent
++ // interface.
++ networkInterfacePath = ancestorMap.begin()->first;
++ }
++ catch (InternalFailure& e)
++ {
++ // if there is no ip configured on the system,then
++ // get the network interface object.
++ auto networkInterfaceObject = ipmi::getDbusObject(
++ bus, ipmi::network::ETHERNET_INTERFACE,
++ ipmi::network::ROOT, ethdevice);
++
++ networkInterfacePath = networkInterfaceObject.first;
++ }
++
++ ipmi::Value ipEnablesProp = ipmi::getDbusProperty(
++ bus, ipmi::network::SERVICE, networkInterfacePath,
++ ipmi::network::ETHERNET_INTERFACE, "IPAddressEnables");
++ std::string ipEnables = std::get<std::string>(ipEnablesProp);
++
++ // check if on off ipv4 ipv6, etc.
++ bool found = false;
++ for (uint8_t ii = 0; ii < ipAddressEnablesType.size(); ii++)
++ {
++ if (ipEnables == ipAddressEnablesType[ii])
++ {
++ ipVAddressEnables = ii;
++ found = true;
++ break;
++ }
++ }
++ if (!found)
++ {
++ return IPMI_CC_PARM_NOT_SUPPORTED;
++ }
++ }
++ else
++ {
++ ipVAddressEnables = channelConf->ipv6AddressingEnables;
++ }
++
++ std::array<uint8_t, 2> buf = {current_revision, ipVAddressEnables};
++ std::copy(buf.begin(), buf.end(), static_cast<uint8_t*>(response));
++ *data_len = buf.size();
++ break;
++ }
++ case LanParam::IPV6_STATUS:
++ {
++ // Number of IPV6 addresses that are supported
++ constexpr std::array<uint8_t, 3> statusData = {1, 1, 3};
++
++ std::array<uint8_t, 4> buf = {current_revision, statusData[0],
++ statusData[1], statusData[2]};
++ std::copy(buf.begin(), buf.end(), static_cast<uint8_t*>(response));
++ *data_len = buf.size();
++ break;
++ }
++ case LanParam::IPV6_STATIC_ADDRESSES:
++ {
++ // Only return set selector 0
++ uint8_t ipv6SetSelector = 0;
++ std::string ipaddress;
++ auto ethIP = ethdevice + "/" + ipmi::network::IPV6_TYPE;
++ uint8_t ipv6AddressSource = 0;
++ uint8_t prefixLength = 0;
++ uint8_t status = 0;
++ if (channelConf->lan_set_in_progress == SET_COMPLETE)
++ {
++ try
++ {
++ auto ipObjectInfo =
++ ipmi::getIPObject(bus, ipmi::network::IP_INTERFACE,
++ ipmi::network::ROOT, ethIP);
++
++ auto properties = ipmi::getAllDbusProperties(
++ bus, ipObjectInfo.second, ipObjectInfo.first,
++ ipmi::network::IP_INTERFACE);
++
++ if (std::get<std::string>(properties["Origin"]) ==
++ "xyz.openbmc_project.Network.IP.AddressOrigin.Static")
++ {
++ ipaddress =
++ std::get<std::string>(properties["Address"]);
++ ipv6AddressSource = 0x81; // Looking at bit 0 and bit 7
++ prefixLength =
++ std::get<uint8_t>(properties["PrefixLength"]);
++ status = 0;
++ }
++ }
++ // ignore the exception, as it is a valid condition that
++ // the system is not configured with any IP.
++ catch (InternalFailure& e)
++ {
++ // nothing to do.
++ }
++ }
++ else if (channelConf->lan_set_in_progress == SET_IN_PROGRESS)
++ {
++ ipv6AddressSource = channelConf->ipv6AddressSource;
++ ipaddress = channelConf->ipv6Addr.c_str();
++ prefixLength = channelConf->ipv6Prefix;
++ status = 1;
++ }
++
++ std::array<uint8_t, ipmi::network::IPV6_ADDRESS_STATUS_SIZE> buf = {
++ current_revision, ipv6SetSelector, ipv6AddressSource};
++ inet_pton(AF_INET6, ipaddress.c_str(),
++ reinterpret_cast<void*>(&buf[3]));
++ buf[20] = prefixLength;
++ buf[21] = status;
++
++ std::copy(buf.begin(), buf.end(), static_cast<uint8_t*>(response));
++ *data_len = buf.size();
++ break;
++ }
++ case LanParam::IPV6_DHCPV6_STATIC_DUID_STORAGE_LENGTH:
++ {
++ // DHCP unique identified
++ // Only 1 read-only 16-byte Block needed
++ uint8_t duidLength = 1;
++ std::array<uint8_t, 2> buf = {current_revision, duidLength};
++ std::copy(buf.begin(), buf.end(), static_cast<uint8_t*>(response));
++ *data_len = buf.size();
++ break;
++ }
++ case LanParam::IPV6_DHCPV6_STATIC_DUIDS:
++ {
++ std::string macAddress;
++ if (channelConf->lan_set_in_progress == SET_COMPLETE)
++ {
++ auto macObjectInfo =
++ ipmi::getDbusObject(bus, ipmi::network::MAC_INTERFACE,
++ ipmi::network::ROOT, ethdevice);
++
++ auto variant = ipmi::getDbusProperty(
++ bus, macObjectInfo.second, macObjectInfo.first,
++ ipmi::network::MAC_INTERFACE, "MACAddress");
++
++ macAddress = std::get<std::string>(variant);
++ }
++ else if (channelConf->lan_set_in_progress == SET_IN_PROGRESS)
++ {
++ macAddress = channelConf->macAddress;
++ }
++
++ std::array<uint8_t,
++ ipmi::network::IPV6_DUID_SIZE + sizeof(current_revision)>
++ buf;
++ buf = {current_revision,
++ reqptr->parameter_set,
++ reqptr->parameter_block,
++ DUID_LEN,
++ 0, // Filler byte
++ DUID_LL_TYPE,
++ 0, // Filler byte
++ DUIC_ETH_HW_TYPE};
++ sscanf(macAddress.c_str(), ipmi::network::MAC_ADDRESS_FORMAT,
++ (&buf[8]), (&buf[9]), (&buf[10]), (&buf[11]), (&buf[12]),
++ (&buf[13]));
++
++ std::copy(buf.begin(), buf.end(), static_cast<uint8_t*>(response));
++ *data_len = buf.size();
++ break;
++ }
++ case LanParam::IPV6_DYNAMIC_ADDRESSES:
++ {
++ std::string ipaddress;
++ uint8_t ipv6AddressSource = 0;
++ uint8_t prefixLength = 0;
++ uint8_t status = 0;
++ auto ethIP = ethdevice + "/" + ipmi::network::IPV6_TYPE;
++
++ if (channelConf->lan_set_in_progress == SET_COMPLETE)
++ {
++ try
++ {
++ auto ipObjectInfo =
++ ipmi::getIPObject(bus, ipmi::network::IP_INTERFACE,
++ ipmi::network::ROOT, ethIP);
++
++ auto properties = ipmi::getAllDbusProperties(
++ bus, ipObjectInfo.second, ipObjectInfo.first,
++ ipmi::network::IP_INTERFACE);
++
++ if (std::get<std::string>(properties["Origin"]) ==
++ "xyz.openbmc_project.Network.IP.AddressOrigin.DHCP")
++ {
++ ipaddress =
++ std::get<std::string>(properties["Address"]);
++ ipv6AddressSource = 0x81; // Looking at bit 0 and bit 7
++ prefixLength =
++ std::get<uint8_t>(properties["PrefixLength"]);
++ status = 0;
++ }
++ else
++ {
++ status = 1;
++ }
++ }
++ // ignore the exception, as it is a valid condition that
++ // the system is not configured with any IP.
++ catch (InternalFailure& e)
++ {
++ // nothing to do.
++ }
++ }
++ else if (channelConf->lan_set_in_progress == SET_IN_PROGRESS)
++ {
++ ipaddress = channelConf->ipv6Addr;
++ ipv6AddressSource = channelConf->ipv6AddressSource;
++ prefixLength = channelConf->ipv6Prefix;
++ status = channelConf->ipv6AddressStatus;
++ }
++
++ uint8_t ipv6SetSelector = 0;
++ std::array<uint8_t, 22> buf = {current_revision, ipv6SetSelector,
++ ipv6AddressSource};
++ inet_pton(AF_INET6, ipaddress.c_str(),
++ reinterpret_cast<void*>(&buf[3]));
++ buf[20] = prefixLength;
++ buf[21] = status;
++
++ std::copy(buf.begin(), buf.end(), static_cast<uint8_t*>(response));
++ *data_len = buf.size();
++ break;
++ }
++ case LanParam::IPV6_DHCPV6_DYNAMIC_DUID_STOR_LEN:
++ {
++ uint8_t duidLength = 0;
++ // Only 1 read-only 16-byte Block needed
++ duidLength = 1;
++
++ std::array<uint8_t, 2> buf = {current_revision, duidLength};
++ std::copy(buf.begin(), buf.end(), static_cast<uint8_t*>(response));
++ *data_len = buf.size();
++ break;
++ }
++ case LanParam::IPV6_DHCPV6_DYNAMIC_DUIDS:
++ {
++ std::string macAddress;
++ if (channelConf->lan_set_in_progress == SET_COMPLETE)
++ {
++ auto macObjectInfo =
++ ipmi::getDbusObject(bus, ipmi::network::MAC_INTERFACE,
++ ipmi::network::ROOT, ethdevice);
++
++ auto variant = ipmi::getDbusProperty(
++ bus, macObjectInfo.second, macObjectInfo.first,
++ ipmi::network::MAC_INTERFACE, "MACAddress");
++
++ macAddress = std::get<std::string>(variant);
++ }
++ else if (channelConf->lan_set_in_progress == SET_IN_PROGRESS)
++ {
++ macAddress = channelConf->macAddress;
++ }
++
++ std::array<uint8_t,
++ ipmi::network::IPV6_DUID_SIZE + sizeof(current_revision)>
++ buf;
++ buf = {current_revision,
++ reqptr->parameter_set,
++ reqptr->parameter_block,
++ DUID_LEN,
++ 0, // Filler byte
++ DUID_LL_TYPE,
++ 0, // Filler byte
++ DUIC_ETH_HW_TYPE};
++
++ sscanf(macAddress.c_str(), ipmi::network::MAC_ADDRESS_FORMAT,
++ (&buf[8]), (&buf[9]), (&buf[10]), (&buf[11]), (&buf[12]),
++ (&buf[13]));
++
++ std::copy(buf.begin(), buf.end(), static_cast<uint8_t*>(response));
++ *data_len = buf.size();
++ break;
++ }
++ case LanParam::IPV6_ROUTER_ADDRESS_CONF_CTRL:
++ {
++ // Determine if automated router discovery occurs when static
++ // addresses are used for the bmc
++
++ auto ethIP = ethdevice + "/" + ipmi::network::IPV6_TYPE;
++ std::string networkInterfacePath;
++ uint8_t dynamicRA;
++ if (channelConf->lan_set_in_progress == SET_COMPLETE)
++ {
++
++ try
++ {
++ ipmi::ObjectTree ancestorMap;
++ // if the system is having ip object,then
++ // get the IP object.
++ auto ipObject =
++ ipmi::getDbusObject(bus, ipmi::network::IP_INTERFACE,
++ ipmi::network::ROOT, ethIP);
++
++ // Get the parent interface of the IP object.
++ try
++ {
++ ipmi::InterfaceList interfaces;
++ interfaces.emplace_back(
++ ipmi::network::ETHERNET_INTERFACE);
++
++ ancestorMap = ipmi::getAllAncestors(
++ bus, ipObject.first, std::move(interfaces));
++ }
++ catch (InternalFailure& e)
++ {
++ // if unable to get the parent interface
++ // then commit the error and return.
++ log<level::ERR>(
++ "Unable to get the parent interface",
++ entry("PATH=%s", ipObject.first.c_str()),
++ entry("INTERFACE=%s",
++ ipmi::network::ETHERNET_INTERFACE));
++ return IPMI_CC_UNSPECIFIED_ERROR;
++ }
++ // for an ip object there would be single parent
++ // interface.
++ networkInterfacePath = ancestorMap.begin()->first;
++ }
++ catch (InternalFailure& e)
++ {
++ // if there is no ip configured on the system,then
++ // get the network interface object.
++ auto networkInterfaceObject = ipmi::getDbusObject(
++ bus, ipmi::network::ETHERNET_INTERFACE,
++ ipmi::network::ROOT, ethdevice);
++
++ networkInterfacePath = networkInterfaceObject.first;
++ }
++
++ auto variant = ipmi::getDbusProperty(
++ bus, ipmi::network::SERVICE, networkInterfacePath,
++ ipmi::network::ETHERNET_INTERFACE, "IPv6AcceptRA");
++ dynamicRA = std::get<bool>(variant);
++ }
++ else
++ {
++ dynamicRA = channelConf->ipv6RouterAddressConfigControl;
++ }
++
++ std::array<uint8_t, 2> buf = {current_revision, dynamicRA};
++ std::copy(buf.begin(), buf.end(), static_cast<uint8_t*>(response));
++ *data_len = buf.size();
++ break;
++ }
++ case LanParam::IPV6_STATIC_ROUTER_1_IP_ADDR:
++ {
++ std::array<uint8_t, ipmi::network::IPV6_ADDRESS_SIZE_BYTE +
++ sizeof(current_revision)>
++ buf = {current_revision};
++ inet_pton(AF_INET6, channelConf->ipv6GatewayAddr.c_str(),
++ reinterpret_cast<void*>(&buf[1]));
++ std::copy(buf.begin(), buf.end(), static_cast<uint8_t*>(response));
++ *data_len = buf.size();
++ break;
++ }
++ case LanParam::IPV6_STATIC_ROUTER_1_PREFIX_LEN:
++ {
++ std::array<uint8_t, 2> buf = {current_revision,
++ channelConf->ipv6GatewayPrefixLength};
++ std::copy(buf.begin(), buf.end(), static_cast<uint8_t*>(response));
++ *data_len = buf.size();
++ break;
++ }
++ case LanParam::IPV6_STATIC_ROUTER_1_PREFIX_VAL:
++ {
++ constexpr uint8_t setSelector = 0;
++ std::array<uint8_t, sizeof(setSelector) +
++ ipmi::network::IPV6_ADDRESS_SIZE_BYTE +
++ sizeof(current_revision)>
++ buf = {current_revision, setSelector};
++
++ inet_pton(AF_INET6, channelConf->ipv6GatewayPrefixValue.c_str(),
++ reinterpret_cast<void*>(&buf[2]));
++
++ std::copy(buf.begin(), buf.end(), static_cast<uint8_t*>(response));
++ *data_len = buf.size();
++ break;
++ }
++ case LanParam::IPV6_STATIC_ROUTER_2_IP_ADDR:
++ {
++ std::array<uint8_t, ipmi::network::IPV6_ADDRESS_SIZE_BYTE +
++ sizeof(current_revision)>
++ buf = {current_revision};
++ inet_pton(AF_INET6, channelConf->ipv6BackupGatewayAddr.c_str(),
++ reinterpret_cast<void*>(&buf[1]));
++ std::copy(buf.begin(), buf.end(), static_cast<uint8_t*>(response));
++ *data_len = buf.size();
++ break;
++ }
++ case LanParam::IPV6_STATIC_ROUTER_2_PREFIX_LEN:
++ {
++ std::array<uint8_t, 2> buf = {
++ current_revision, channelConf->ipv6BackupGatewayPrefixLength};
++ std::copy(buf.begin(), buf.end(), static_cast<uint8_t*>(response));
++ *data_len = buf.size();
++ break;
++ }
++ case LanParam::IPV6_STATIC_ROUTER_2_PREFIX_VAL:
++ {
++
++ constexpr uint8_t setSelector = 0;
++ std::array<uint8_t, sizeof(setSelector) +
++ ipmi::network::IPV6_ADDRESS_SIZE_BYTE +
++ sizeof(current_revision)>
++ buf = {current_revision, setSelector};
++ inet_pton(AF_INET6,
++ channelConf->ipv6BackupGatewayPrefixValue.c_str(),
++ reinterpret_cast<void*>(&buf[2]));
++
++ std::copy(buf.begin(), buf.end(), static_cast<uint8_t*>(response));
++ *data_len = buf.size();
++ break;
++ }
+ default:
+ log<level::ERR>("Unsupported parameter",
+ entry("PARAMETER=0x%x", reqptr->parameter));
+@@ -957,6 +1580,16 @@ void applyChanges(int channel)
+ ipaddress, prefix);
+ }
+
++ if (!channelConf->ipv6Addr.empty() &&
++ channelConf->ipv6AddressSource ==
++ 0x80) // Check if IPv6 static addresses are enabled
++ {
++ ipmi::network::createIP(bus, ipmi::network::SERVICE,
++ networkInterfacePath, ipv6Protocol,
++ channelConf->ipv6Addr,
++ channelConf->ipv6Prefix);
++ }
++
+ if (!gateway.empty())
+ {
+ ipmi::setDbusProperty(bus, systemObject.second,
+@@ -964,7 +1597,24 @@ void applyChanges(int channel)
+ ipmi::network::SYSTEMCONFIG_INTERFACE,
+ "DefaultGateway", std::string(gateway));
+ }
++ else if (!channelConf->ipv6GatewayAddr.empty())
++ {
++ ipmi::setDbusProperty(
++ bus, systemObject.second, systemObject.first,
++ ipmi::network::SYSTEMCONFIG_INTERFACE, "DefaultGateway",
++ std::string(channelConf->ipv6GatewayAddr));
++ }
+ }
++ // set IPAddress Enables
++ ipmi::setDbusProperty(
++ bus, ipmi::network::SERVICE, networkInterfaceObject.first,
++ ipmi::network::ETHERNET_INTERFACE, "IPAddressEnables",
++ ipAddressEnablesType[channelConf->ipv6AddressingEnables]);
++
++ ipmi::setDbusProperty(
++ bus, ipmi::network::SERVICE, networkInterfaceObject.first,
++ ipmi::network::ETHERNET_INTERFACE, "IPv6AcceptRA",
++ (bool)channelConf->ipv6RouterAddressConfigControl);
+ }
+ catch (sdbusplus::exception::exception& e)
+ {
+Index: phosphor-host-ipmid.clean/transporthandler.hpp
+===================================================================
+--- phosphor-host-ipmid.clean.orig/transporthandler.hpp
++++ phosphor-host-ipmid.clean/transporthandler.hpp
+@@ -79,8 +79,27 @@ enum class LanParam : uint8_t
+ IPV6_NEIGHBOR_TIMING_CONFIGURATION = 80,
+ };
+
++constexpr uint8_t DUID_LEN = 10;
++constexpr uint8_t DUID_LL_TYPE = 3;
++constexpr uint8_t DUIC_ETH_HW_TYPE = 1;
++
+ // Data length of parameters
+ constexpr size_t lanParamVLANSize = 4;
++constexpr size_t lanParamInProgressSize = 3;
++constexpr size_t lanParamIPSize = 6;
++constexpr size_t lanParamIPSrcSize = 3;
++constexpr size_t lanParamMACSize = 8;
++constexpr size_t lanParamSubnetSize = 6;
++constexpr size_t lanParamGatewaySize = 6;
++constexpr size_t lanParamIPv6AndIPv4EnablesSize = 3;
++constexpr size_t lanParamIPv6StaticAddressesSize = 23;
++constexpr size_t lanParamIPv6RouterAddressConfCtrlSize = 3;
++constexpr size_t lanParamIPv6StaticRouter1IPAddrSize = 18;
++constexpr size_t lanParamIPv6StaticRouter1PrefixLenSize = 3;
++constexpr size_t lanParamIPv6StaticRouter1PrefixValSize = 19;
++constexpr size_t lanParamIPv6StaticRouter2IPAddrSize = 18;
++constexpr size_t lanParamIPv6StaticRouter2PrefixLenSize = 3;
++constexpr size_t lanParamIPv6StaticRouter2PrefixValSize = 19;
+ constexpr uint8_t SET_COMPLETE = 0;
+ constexpr uint8_t SET_IN_PROGRESS = 1;
+ constexpr uint8_t SET_COMMIT_WRITE = 2; // Optional
+@@ -103,6 +122,20 @@ struct ChannelConfig_t
+ uint8_t lan_set_in_progress = SET_COMPLETE;
+ bool flush = false;
+
++ // IPV6 parameters
++ uint8_t ipv6AddressSource = 0x0;
++ uint8_t ipv6AddressingEnables = 0x2;
++ std::string ipv6Addr;
++ uint8_t ipv6Prefix = 32;
++ uint8_t ipv6AddressStatus = 0x0;
++ uint8_t ipv6RouterAddressConfigControl = 0x0;
++ std::string ipv6GatewayAddr;
++ std::string ipv6BackupGatewayAddr;
++ uint8_t ipv6GatewayPrefixLength;
++ std::string ipv6GatewayPrefixValue;
++ uint8_t ipv6BackupGatewayPrefixLength = 0x0;
++ std::string ipv6BackupGatewayPrefixValue;
++
+ void clear()
+ {
+ ipaddr.clear();
+@@ -113,6 +146,20 @@ struct ChannelConfig_t
+ ipsrc = ipmi::network::IPOrigin::UNSPECIFIED;
+ lan_set_in_progress = SET_COMPLETE;
+ flush = false;
++
++ // IPv6
++ ipv6Addr.clear();
++ ipv6GatewayAddr.clear();
++ ipv6BackupGatewayAddr.clear();
++ ipv6AddressingEnables = 0x2;
++ ipv6AddressSource = 0x0;
++ ipv6Prefix = 32;
++ ipv6AddressStatus = 0x0;
++ ipv6RouterAddressConfigControl = 0x0;
++ ipv6GatewayPrefixLength = 0x0;
++ ipv6GatewayPrefixValue.clear();
++ ipv6BackupGatewayPrefixLength = 0x0;
++ ipv6BackupGatewayPrefixValue.clear();
+ }
+ };
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0010-fix-get-system-GUID-ipmi-command.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0010-fix-get-system-GUID-ipmi-command.patch
new file mode 100644
index 000000000..efee7cc26
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0010-fix-get-system-GUID-ipmi-command.patch
@@ -0,0 +1,36 @@
+commit 72e6573f36fd3b9ce018e71b07bc1be63275d1f8
+Author: Vernon Mauery <vernon.mauery@linux.intel.com>
+Date: Fri Jun 21 12:27:20 2019 -0700
+
+ Fix 'Get System GUID' to use settings UUID
+
+ The upstream Get System GUID command looks first for a BMC interface
+ and then assumes that the UUID interface is next to that. But that is
+ not the case on Intel systems where the system GUID is found in the
+ settings daemon.
+
+ Change-Id: I924bd05e0a546f2b30288c1faf72157296ab6579
+ Signed-off-by: Vernon Mauery <vernon.mauery@linux.intel.com>
+
+diff --git a/apphandler.cpp b/apphandler.cpp
+index 280d0db..25af6bb 100644
+--- a/apphandler.cpp
++++ b/apphandler.cpp
+@@ -799,8 +799,6 @@ auto ipmiAppGetBtCapabilities()
+
+ auto ipmiAppGetSystemGuid() -> ipmi::RspType<std::array<uint8_t, 16>>
+ {
+- static constexpr auto bmcInterface =
+- "xyz.openbmc_project.Inventory.Item.Bmc";
+ static constexpr auto uuidInterface = "xyz.openbmc_project.Common.UUID";
+ static constexpr auto uuidProperty = "UUID";
+
+@@ -809,7 +807,7 @@ auto ipmiAppGetSystemGuid() -> ipmi::RspType<std::array<uint8_t, 16>>
+ {
+ // Get the Inventory object implementing BMC interface
+ auto busPtr = getSdBus();
+- auto objectInfo = ipmi::getDbusObject(*busPtr, bmcInterface);
++ auto objectInfo = ipmi::getDbusObject(*busPtr, uuidInterface);
+
+ // Read UUID property value from bmcObject
+ // UUID is in RFC4122 format Ex: 61a39523-78f2-11e5-9862-e6402cfc3223
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0013-ipmi-add-set-bios-id-to-whitelist.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0013-ipmi-add-set-bios-id-to-whitelist.patch
new file mode 100644
index 000000000..396d2e949
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0013-ipmi-add-set-bios-id-to-whitelist.patch
@@ -0,0 +1,22 @@
+From ad7276f3aedb6f5aed315db57406c98f2bf71a09 Mon Sep 17 00:00:00 2001
+From: "Jia, Chunhui" <chunhui.jia@intel.com>
+Date: Tue, 24 Jul 2018 13:21:52 +0800
+Subject: [PATCH] [ipmi] add set bios id to whitelist
+
+Add "SetBIOSId" and "GetDeviceInfo" 2 OEM commands into whitelist
+
+Signed-off-by: Jia, Chunhui <chunhui.jia@intel.com>
+---
+ host-ipmid-whitelist.conf | 2 ++
+ 1 file changed, 2 insertions(+)
+
+Index: phosphor-host-ipmid/host-ipmid-whitelist.conf
+===================================================================
+--- phosphor-host-ipmid.orig/host-ipmid-whitelist.conf
++++ phosphor-host-ipmid/host-ipmid-whitelist.conf
+@@ -47,3 +47,5 @@
+ 0x2C:0x06 //<Group Extension>:<Get Asset Tag>
+ 0x2C:0x07 //<Group Extension>:<Get Sensor Info>
+ 0x2C:0x10 //<Group Extension>:<Get Temperature Readings>
++0x30:0x26 //<OEM>:<Set BIOS ID>
++0x30:0x27 //<OEM>:<Get Device Info>
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0039-ipmi-add-oem-command-get-AIC-FRU-to-whitelist.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0039-ipmi-add-oem-command-get-AIC-FRU-to-whitelist.patch
new file mode 100644
index 000000000..fdaa91085
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0039-ipmi-add-oem-command-get-AIC-FRU-to-whitelist.patch
@@ -0,0 +1,25 @@
+From cf466ba2c66a95825ae0014d7c378ad63b050d2f Mon Sep 17 00:00:00 2001
+From: "Jia, Chunhui" <chunhui.jia@intel.com>
+Date: Wed, 15 Aug 2018 14:50:04 +0800
+Subject: [PATCH] [ipmi] add oem command "get AIC FRU" to whitelist
+
+Intel BIOS requires this oem command to get addon card FRU info.
+Add to whitelist to unblock.
+
+Signed-off-by: Jia, Chunhui <chunhui.jia@intel.com>
+---
+ host-ipmid-whitelist.conf | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/host-ipmid-whitelist.conf b/host-ipmid-whitelist.conf
+index db54a49..49746a2 100644
+--- a/host-ipmid-whitelist.conf
++++ b/host-ipmid-whitelist.conf
+@@ -43,3 +43,4 @@
+ 0x30:0x41 //<OEM>:<Set System GUID>
+ 0x30:0x26 //<OEM>:<Set BIOS ID>
+ 0x30:0x27 //<OEM>:<Get Device Info>
++0x30:0x31 //<OEM>:<Get AIC card FRU>
+--
+2.16.2
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0050-enable-6-oem-commands.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0050-enable-6-oem-commands.patch
new file mode 100644
index 000000000..b800632cc
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0050-enable-6-oem-commands.patch
@@ -0,0 +1,15 @@
+diff --git a/host-ipmid-whitelist.conf b/host-ipmid-whitelist.conf
+index 22a2a3c..5d71698 100644
+--- a/host-ipmid-whitelist.conf
++++ b/host-ipmid-whitelist.conf
+@@ -49,3 +49,10 @@
+ 0x30:0x26 //<OEM>:<Set BIOS ID>
+ 0x30:0x27 //<OEM>:<Get Device Info>
+ 0x30:0x31 //<OEM>:<Get AIC card FRU>
++0x30:0x54 //<OEM>:<Set Power Restore Delay>
++0x30:0x55 //<OEM>:<Get Power Restore Delay>
++0x30:0x9A //<OEM>:<Get Processor Error Config>
++0x30:0x9B //<OEM>:<Set Processor Error Config>
++0x30:0xB0 //<OEM>:<Get LED Status>
++0x30:0xE9 //<OEM>:<Get BIOS Post Codes>
++
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0053-Fix-keep-looping-issue-when-entering-OS.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0053-Fix-keep-looping-issue-when-entering-OS.patch
new file mode 100644
index 000000000..903ae96a7
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0053-Fix-keep-looping-issue-when-entering-OS.patch
@@ -0,0 +1,80 @@
+From ad93a6e17310d92ef07b8d367b23c93793562d0f Mon Sep 17 00:00:00 2001
+From: Cheng C Yang <cheng.c.yang@linux.intel.com>
+Date: Wed, 23 Jan 2019 17:02:40 +0800
+Subject: [PATCH] Fix keep looping issue when entering OS
+
+Sometimes when entering OS, OS will keep continuously sending ipmi command
+"READ EVENT MESSAGE BUFFER" to BMC. This issue is caused by incorrect KCS
+status. If restart the host immediately while OS is still running, SMS_ATN
+will be set, after that KCS come into an incorrect status, and then KCS
+communction between BMC and OS crash. To make KCS go back to correct status
+and fix the issue, clear SMS_ATN after every time power cycle happen.
+
+Unit Test:
+ After entered OS, force reset system, after enter OS again, OS can start
+normally without keep sending READ EVENT MESSAGE BUFFER command.
+ After power on system, enter EFI SHELL, check cmdtool.efi can work
+correctly through KCS channel.
+---
+ host-cmd-manager.cpp | 24 ++++++++++++++++++------
+ 1 file changed, 18 insertions(+), 6 deletions(-)
+
+diff --git a/host-cmd-manager.cpp b/host-cmd-manager.cpp
+index f3aba7f..465eb81 100644
+--- a/host-cmd-manager.cpp
++++ b/host-cmd-manager.cpp
+@@ -26,6 +26,8 @@ constexpr auto MAPPER_INTERFACE = "xyz.openbmc_project.ObjectMapper";
+ constexpr auto HOST_STATE_PATH = "/xyz/openbmc_project/state/host0";
+ constexpr auto HOST_STATE_INTERFACE = "xyz.openbmc_project.State.Host";
+ constexpr auto HOST_TRANS_PROP = "RequestedHostTransition";
++constexpr const char* IPMI_PATH = "/xyz/openbmc_project/Ipmi/Channel/ipmi_kcs3";
++constexpr const char* IPMI_INTERFACE = "xyz.openbmc_project.Ipmi.Channel.SMS";
+
+ // For throwing exceptions
+ using namespace phosphor::logging;
+@@ -106,6 +108,20 @@ void Manager::clearQueue()
+ // `false` indicating Failure
+ std::get<CallBack>(command)(ipmiCmdData, false);
+ }
++
++ auto host = ::ipmi::getService(this->bus, IPMI_INTERFACE, IPMI_PATH);
++ auto method = this->bus.new_method_call(host.c_str(), IPMI_PATH,
++ IPMI_INTERFACE, "clearAttention");
++
++ try
++ {
++ auto reply = this->bus.call(method);
++ }
++ catch (sdbusplus::exception_t&)
++ {
++ log<level::ERR>("Error in clearing SMS attention");
++ elog<InternalFailure>();
++ }
+ }
+
+ // Called for alerting the host
+@@ -115,9 +131,6 @@ void Manager::checkQueueAndAlertHost()
+ {
+ log<level::DEBUG>("Asserting SMS Attention");
+
+- std::string IPMI_PATH("/org/openbmc/HostIpmi/1");
+- std::string IPMI_INTERFACE("org.openbmc.HostIpmi");
+-
+ auto host = ::ipmi::getService(this->bus, IPMI_INTERFACE, IPMI_PATH);
+
+ // Start the timer for this transaction
+@@ -131,9 +144,8 @@ void Manager::checkQueueAndAlertHost()
+ return;
+ }
+
+- auto method =
+- this->bus.new_method_call(host.c_str(), IPMI_PATH.c_str(),
+- IPMI_INTERFACE.c_str(), "setAttention");
++ auto method = this->bus.new_method_call(host.c_str(), IPMI_PATH,
++ IPMI_INTERFACE, "setAttention");
+ auto reply = this->bus.call(method);
+
+ if (reply.is_method_error())
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0054-Fix-User-commands-require-channel-layer-lib.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0054-Fix-User-commands-require-channel-layer-lib.patch
new file mode 100644
index 000000000..bf6f672cf
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0054-Fix-User-commands-require-channel-layer-lib.patch
@@ -0,0 +1,37 @@
+From 5d0c9d2217dbe369daffb8a92d7b5e7d7d34d566 Mon Sep 17 00:00:00 2001
+From: Richard Marian Thomaiyar <richard.marian.thomaiyar@linux.intel.com>
+Date: Sat, 2 Mar 2019 20:08:32 +0530
+Subject: [PATCH] Fix: User commands require channel layer lib
+
+As channel layer is separated out from user layer lib, it
+has to be manually included in libusercommands, as user
+command handlers use channel layer API's
+
+Tested-by:
+1. Made sure that libusercommands are loaded on it's own
+without any undefined symbol error.
+2. ipmitool user list 1 works on host interface
+
+Change-Id: I6652ad248e01afc1349e3a9612754dbdb84b96ad
+Signed-off-by: Richard Marian Thomaiyar <richard.marian.thomaiyar@linux.intel.com>
+---
+ Makefile.am | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/Makefile.am b/Makefile.am
+index bb7bdbf..4e9101e 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -120,7 +120,8 @@ libipmi20_la_CXXFLAGS = $(COMMON_CXX)
+ providers_LTLIBRARIES += libusercmds.la
+ libusercmds_la_LIBADD = \
+ libipmid/libipmid.la \
+- user_channel/libuserlayer.la
++ user_channel/libuserlayer.la \
++ user_channel/libchannellayer.la
+ libusercmds_la_SOURCES = \
+ user_channel/usercommands.cpp
+ libusercmds_la_LDFLAGS = \
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0056-add-SetInProgress-to-get-set-boot-option-cmd.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0056-add-SetInProgress-to-get-set-boot-option-cmd.patch
new file mode 100644
index 000000000..3a77887a0
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0056-add-SetInProgress-to-get-set-boot-option-cmd.patch
@@ -0,0 +1,102 @@
+From 949db3a985719335d3df77db368eb2b296756749 Mon Sep 17 00:00:00 2001
+From: "Jia, chunhui" <chunhui.jia@linux.intel.com>
+Date: Tue, 19 Mar 2019 16:09:06 +0800
+Subject: [PATCH] add SetInProgress to get/set boot option cmd
+
+It is required by BIOS. BIOS will check setinprogress first.
+If this flag is not supported, BIOS will bypass all boot
+option flow.
+
+Change-Id: Ibb0501ea5bc36c4f1f72339efef03724dd4e613f
+Signed-off-by: Jia, chunhui <chunhui.jia@linux.intel.com>
+---
+ chassishandler.cpp | 26 +++++++++++++++++++++++++-
+ chassishandler.hpp | 3 +++
+ 2 files changed, 28 insertions(+), 1 deletion(-)
+
+diff --git a/chassishandler.cpp b/chassishandler.cpp
+index 6d14d1b..553afa8 100644
+--- a/chassishandler.cpp
++++ b/chassishandler.cpp
+@@ -1351,6 +1351,10 @@ static ipmi_ret_t setBootMode(const Mode::Modes& mode)
+ return IPMI_CC_OK;
+ }
+
++static constexpr uint8_t setComplete = 0x0;
++static constexpr uint8_t setInProgress = 0x1;
++static uint8_t transferStatus = setComplete;
++
+ ipmi_ret_t ipmi_chassis_get_sys_boot_options(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+ ipmi_request_t request,
+ ipmi_response_t response,
+@@ -1365,11 +1369,21 @@ ipmi_ret_t ipmi_chassis_get_sys_boot_options(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+ get_sys_boot_options_t* reqptr = (get_sys_boot_options_t*)request;
+ IpmiValue bootOption = ipmiDefault;
+
++ if (reqptr->parameter ==
++ static_cast<uint8_t>(BootOptionParameter::SET_IN_PROGRESS))
++ {
++ *data_len =
++ static_cast<uint8_t>(BootOptionResponseSize::SET_IN_PROGRESS);
++ resp->version = SET_PARM_VERSION;
++ resp->parm = static_cast<uint8_t>(BootOptionParameter::SET_IN_PROGRESS);
++ resp->data[0] = transferStatus;
++ return IPMI_CC_OK;
++ }
++
+ std::memset(resp, 0, sizeof(*resp));
+ resp->version = SET_PARM_VERSION;
+ resp->parm = 5;
+ resp->data[0] = SET_PARM_BOOT_FLAGS_VALID_ONE_TIME;
+-
+ /*
+ * Parameter #5 means boot flags. Please refer to 28.13 of ipmi doc.
+ * This is the only parameter used by petitboot.
+@@ -1505,6 +1519,16 @@ ipmi_ret_t ipmi_chassis_set_sys_boot_options(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+ // This IPMI command does not have any resposne data
+ *data_len = 0;
+
++ if (reqptr->parameter ==
++ static_cast<uint8_t>(BootOptionParameter::SET_IN_PROGRESS))
++ {
++ if (transferStatus == setInProgress) {
++ return IPMI_CC_FAIL_SET_IN_PROGRESS;
++ }
++ transferStatus = reqptr->data[0];
++ return IPMI_CC_OK;
++ }
++
+ /* 000101
+ * Parameter #5 means boot flags. Please refer to 28.13 of ipmi doc.
+ * This is the only parameter used by petitboot.
+diff --git a/chassishandler.hpp b/chassishandler.hpp
+index 2c42b11..6a24507 100644
+--- a/chassishandler.hpp
++++ b/chassishandler.hpp
+@@ -28,6 +28,7 @@ enum ipmi_chassis_return_codes
+ {
+ IPMI_OK = 0x0,
+ IPMI_CC_PARM_NOT_SUPPORTED = 0x80,
++ IPMI_CC_FAIL_SET_IN_PROGRESS = 0x81,
+ };
+
+ // Generic completion codes,
+@@ -49,6 +50,7 @@ enum ipmi_chassis_control_cmds : uint8_t
+ };
+ enum class BootOptionParameter : size_t
+ {
++ SET_IN_PROGRESS = 0x0,
+ BOOT_INFO = 0x4,
+ BOOT_FLAGS = 0x5,
+ OPAL_NETWORK_SETTINGS = 0x61
+@@ -56,6 +58,7 @@ enum class BootOptionParameter : size_t
+
+ enum class BootOptionResponseSize : size_t
+ {
++ SET_IN_PROGRESS = 3,
+ BOOT_FLAGS = 5,
+ OPAL_NETWORK_SETTINGS = 50
+ };
+--
+2.16.2
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0057-Add-timer-use-actions-support.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0057-Add-timer-use-actions-support.patch
new file mode 100644
index 000000000..f091b31fa
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0057-Add-timer-use-actions-support.patch
@@ -0,0 +1,31 @@
+From 3c69c94eed1a0c6eecfd53e739fade6596c6f3e5 Mon Sep 17 00:00:00 2001
+From: Yong Li <yong.b.li@linux.intel.com>
+Date: Thu, 12 Sep 2019 17:37:05 +0800
+Subject: [PATCH] Add timer use/actions support
+
+Based on IPMI spec, add timer use/actions support,
+and add input data checking
+
+Signed-off-by: Yong Li <yong.b.li@linux.intel.com>
+---
+ app/watchdog.cpp | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/app/watchdog.cpp b/app/watchdog.cpp
+index c4e594d..18e7e3a 100644
+--- a/app/watchdog.cpp
++++ b/app/watchdog.cpp
+@@ -251,8 +251,8 @@ ipmi::RspType<> ipmiSetWatchdogTimer(
+ return ipmi::responseInvalidFieldRequest();
+ }
+
+- timerLogFlags = static_cast<uint8_t>(dontLog);
+- timerActions &= static_cast<uint8_t>(timeoutAction) |
++ timerLogFlags = (static_cast<uint8_t>(dontLog)) << 7;
++ timerActions = static_cast<uint8_t>(timeoutAction) |
+ static_cast<uint8_t>(preTimeoutInterrupt) << 4;
+
+ try
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0059-Move-Set-SOL-config-parameter-to-host-ipmid.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0059-Move-Set-SOL-config-parameter-to-host-ipmid.patch
new file mode 100644
index 000000000..2dad2fc16
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0059-Move-Set-SOL-config-parameter-to-host-ipmid.patch
@@ -0,0 +1,383 @@
+From 27b94aa1df83abad63cbba69525273194b14ab9c Mon Sep 17 00:00:00 2001
+From: Cheng C Yang <cheng.c.yang@intel.com>
+Date: Wed, 16 Oct 2019 14:24:20 +0800
+Subject: [PATCH] Move Set SOL config parameter to host-ipmid
+
+Move Set SOL config parameter command from net-ipmid to host-ipmid,
+so that BIOS in Intel platform can enable or disable SOL through KCS.
+Get SOL config parameter command will be moved later.
+
+Tested by:
+With the related change in phospher-ipmi-net and phospher-dbus-interface,
+Run commands:
+ipmitool raw 0x0c 0x21 0x0e 0x00 0x01
+ipmitool raw 0x0c 0x21 0x0e 0x01 0x00
+ipmitool raw 0x0c 0x21 0x0e 0x02 0x03
+ipmitool raw 0x0c 0x21 0x0e 0x03 0x5 0x03
+ipmitool raw 0x0c 0x21 0x0e 0x04 0x5 0x03
+All these commands have correct response and all dbus interface for
+sol command change to same value in above commands.
+After reboot BMC, "Progress" property in dbus interface change back
+to 0 and other properties will not reset to default value.
+
+Signed-off-by: Cheng C Yang <cheng.c.yang@intel.com>
+---
+ host-ipmid-whitelist.conf | 1 +
+ transporthandler.cpp | 322 ++++++++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 323 insertions(+)
+
+diff --git a/host-ipmid-whitelist.conf b/host-ipmid-whitelist.conf
+index e8df7c7..f030ef4 100644
+--- a/host-ipmid-whitelist.conf
++++ b/host-ipmid-whitelist.conf
+@@ -41,6 +41,7 @@
+ 0x0A:0x48 //<Storage>:<Get SEL Time>
+ 0x0A:0x49 //<Storage>:<Set SEL Time>
+ 0x0C:0x02 //<Transport>:<Get LAN Configuration Parameters>
++0x0C:0x21 //<Transport>:<Set SOL Configuration Parameters>
+ 0x2C:0x00 //<Group Extension>:<Group Extension Command>
+ 0x2C:0x01 //<Group Extension>:<Get DCMI Capabilities>
+ 0x2C:0x02 //<Group Extension>:<Get Power Reading>
+diff --git a/transporthandler.cpp b/transporthandler.cpp
+index e88eb63..4a42e7b 100644
+--- a/transporthandler.cpp
++++ b/transporthandler.cpp
+@@ -1168,8 +1168,323 @@ RspType<message::Payload> getLan(uint4_t channelBits, uint3_t, bool revOnly,
+ } // namespace transport
+ } // namespace ipmi
+
++constexpr const char* solInterface = "xyz.openbmc_project.Ipmi.SOL";
++constexpr const char* solPath = "/xyz/openbmc_project/ipmi/sol/";
++
+ void register_netfn_transport_functions() __attribute__((constructor));
+
++static std::string
++ getSOLService(std::shared_ptr<sdbusplus::asio::connection> dbus,
++ const std::string& solPathWitheEthName)
++{
++ static std::string solService{};
++ if (solService.empty())
++ {
++ try
++ {
++ solService =
++ ipmi::getService(*dbus, solInterface, solPathWitheEthName);
++ }
++ catch (const sdbusplus::exception::SdBusError& e)
++ {
++ solService.clear();
++ phosphor::logging::log<phosphor::logging::level::ERR>(
++ "Error: get SOL service failed");
++ return solService;
++ }
++ }
++ return solService;
++}
++
++static int setSOLParameter(const std::string& property,
++ const ipmi::Value& value, const uint8_t& channelNum)
++{
++ auto dbus = getSdBus();
++
++ std::string ethdevice = ipmi::getChannelName(channelNum);
++
++ std::string solPathWitheEthName = std::string(solPath) + ethdevice;
++
++ std::string service = getSOLService(dbus, solPathWitheEthName);
++ if (service.empty())
++ {
++ phosphor::logging::log<phosphor::logging::level::ERR>(
++ "Unable to get SOL service failed");
++ return -1;
++ }
++ try
++ {
++ ipmi::setDbusProperty(*dbus, service, solPathWitheEthName, solInterface,
++ property, value);
++ }
++ catch (sdbusplus::exception_t&)
++ {
++ phosphor::logging::log<phosphor::logging::level::ERR>(
++ "Error setting sol parameter");
++ return -1;
++ }
++
++ return 0;
++}
++
++static int getSOLParameter(const std::string& property, ipmi::Value& value,
++ const uint8_t& channelNum)
++{
++ auto dbus = getSdBus();
++
++ std::string ethdevice = ipmi::getChannelName(channelNum);
++
++ std::string solPathWitheEthName = std::string(solPath) + ethdevice;
++
++ std::string service = getSOLService(dbus, solPathWitheEthName);
++ if (service.empty())
++ {
++ phosphor::logging::log<phosphor::logging::level::ERR>(
++ "Unable to get SOL service failed");
++ return -1;
++ }
++ try
++ {
++ value = ipmi::getDbusProperty(*dbus, service, solPathWitheEthName,
++ solInterface, property);
++ }
++ catch (sdbusplus::exception_t&)
++ {
++ phosphor::logging::log<phosphor::logging::level::ERR>(
++ "Error getting sol parameter");
++ return -1;
++ }
++
++ return 0;
++}
++
++void initializeSOLInProgress()
++{
++ ipmi::ChannelInfo chInfo;
++ for (int chNum = 0; chNum < ipmi::maxIpmiChannels; chNum++)
++ {
++ if (!ipmi::isValidChannel(static_cast<uint8_t>(chNum)))
++ {
++ continue;
++ }
++ ipmi_ret_t compCode =
++ ipmi::getChannelInfo(static_cast<uint8_t>(chNum), chInfo);
++ if (compCode != IPMI_CC_OK ||
++ chInfo.mediumType !=
++ static_cast<uint8_t>(ipmi::EChannelMediumType::lan8032))
++ {
++ continue;
++ }
++ if (setSOLParameter("Progress", static_cast<uint8_t>(0), chNum) < 0)
++ {
++ phosphor::logging::log<phosphor::logging::level::ERR>(
++ "Error initialize sol progress");
++ }
++ }
++}
++
++static const constexpr uint8_t encryptMask = 0x80;
++static const constexpr uint8_t encryptShift = 7;
++static const constexpr uint8_t authMask = 0x40;
++static const constexpr uint8_t authShift = 6;
++static const constexpr uint8_t privilegeMask = 0xf;
++
++namespace ipmi
++{
++constexpr Cc ccParmNotSupported = 0x80;
++constexpr Cc ccSetInProgressActive = 0x81;
++constexpr Cc ccSystemInfoParameterSetReadOnly = 0x82;
++
++static inline auto responseParmNotSupported()
++{
++ return response(ccParmNotSupported);
++}
++static inline auto responseSetInProgressActive()
++{
++ return response(ccSetInProgressActive);
++}
++static inline auto responseSystemInfoParameterSetReadOnly()
++{
++ return response(ccSystemInfoParameterSetReadOnly);
++}
++
++} // namespace ipmi
++
++namespace sol
++{
++enum class Parameter
++{
++ progress, //!< Set In Progress.
++ enable, //!< SOL Enable.
++ authentication, //!< SOL Authentication.
++ accumulate, //!< Character Accumulate Interval & Send Threshold.
++ retry, //!< SOL Retry.
++ nvbitrate, //!< SOL non-volatile bit rate.
++ vbitrate, //!< SOL volatile bit rate.
++ channel, //!< SOL payload channel.
++ port, //!< SOL payload port.
++};
++
++enum class Privilege : uint8_t
++{
++ highestPriv,
++ callbackPriv,
++ userPriv,
++ operatorPriv,
++ adminPriv,
++ oemPriv,
++};
++
++} // namespace sol
++
++constexpr uint8_t progressMask = 0x03;
++constexpr uint8_t enableMask = 0x01;
++constexpr uint8_t retryMask = 0x07;
++
++ipmi::RspType<> setSOLConfParams(ipmi::Context::ptr ctx, uint4_t chNum,
++ uint4_t reserved, uint8_t paramSelector,
++ uint8_t configParamData1,
++ std::optional<uint8_t> configParamData2)
++{
++ ipmi::ChannelInfo chInfo;
++ uint8_t channelNum = ipmi::convertCurrentChannelNum(
++ static_cast<uint8_t>(chNum), ctx->channel);
++ if (reserved != 0 ||
++ (!ipmi::isValidChannel(static_cast<uint8_t>(channelNum))))
++ {
++ return ipmi::responseInvalidFieldRequest();
++ }
++
++ ipmi_ret_t compCode =
++ ipmi::getChannelInfo(static_cast<uint8_t>(channelNum), chInfo);
++ if (compCode != IPMI_CC_OK ||
++ chInfo.mediumType !=
++ static_cast<uint8_t>(ipmi::EChannelMediumType::lan8032))
++ {
++ return ipmi::responseInvalidFieldRequest();
++ }
++
++ switch (static_cast<sol::Parameter>(paramSelector))
++ {
++ case sol::Parameter::progress:
++ {
++ if (configParamData2)
++ {
++ return ipmi::responseReqDataLenInvalid();
++ }
++ uint8_t progress = configParamData1 & progressMask;
++ ipmi::Value currentProgress = 0;
++ if (getSOLParameter("Progress", currentProgress, channelNum) < 0)
++ {
++ return ipmi::responseUnspecifiedError();
++ }
++
++ if ((std::get<uint8_t>(currentProgress) == 1) && (progress == 1))
++ {
++ return ipmi::responseSetInProgressActive();
++ }
++
++ if (setSOLParameter("Progress", progress, channelNum) < 0)
++ {
++ return ipmi::responseUnspecifiedError();
++ }
++ break;
++ }
++ case sol::Parameter::enable:
++ {
++ if (configParamData2)
++ {
++ return ipmi::responseReqDataLenInvalid();
++ }
++ bool enable = configParamData1 & enableMask;
++ if (setSOLParameter("Enable", enable, channelNum) < 0)
++ {
++ return ipmi::responseUnspecifiedError();
++ }
++ break;
++ }
++ case sol::Parameter::authentication:
++ {
++ if (configParamData2)
++ {
++ return ipmi::responseReqDataLenInvalid();
++ }
++ uint8_t encrypt = (configParamData1 & encryptMask) >> encryptShift;
++ uint8_t auth = (configParamData1 & authMask) >> authShift;
++ uint8_t privilege = configParamData1 & privilegeMask;
++ // For security considering encryption and authentication must be
++ // true.
++ if (!encrypt || !auth)
++ {
++ return ipmi::responseSystemInfoParameterSetReadOnly();
++ }
++ else if (privilege <
++ static_cast<uint8_t>(sol::Privilege::userPriv) ||
++ privilege > static_cast<uint8_t>(sol::Privilege::oemPriv))
++ {
++ return ipmi::responseInvalidFieldRequest();
++ }
++
++ if (setSOLParameter("Privilege", privilege, channelNum) < 0)
++ {
++ return ipmi::responseUnspecifiedError();
++ }
++
++ break;
++ }
++ case sol::Parameter::accumulate:
++ {
++ if (!configParamData2)
++ {
++ return ipmi::responseReqDataLenInvalid();
++ }
++ if (*configParamData2 == 0)
++ {
++ return ipmi::responseInvalidFieldRequest();
++ }
++ if (setSOLParameter("AccumulateIntervalMS", configParamData1,
++ channelNum) < 0)
++ {
++ return ipmi::responseUnspecifiedError();
++ }
++ if (setSOLParameter("Threshold", *configParamData2, channelNum) < 0)
++ {
++ return ipmi::responseUnspecifiedError();
++ }
++ break;
++ }
++ case sol::Parameter::retry:
++ {
++ if (!configParamData2)
++ {
++ return ipmi::responseReqDataLenInvalid();
++ }
++ if ((setSOLParameter(
++ "RetryCount",
++ static_cast<uint8_t>(configParamData1 & retryMask),
++ channelNum) < 0) ||
++ (setSOLParameter("RetryIntervalMS", *configParamData2,
++ channelNum) < 0))
++ {
++ return ipmi::responseUnspecifiedError();
++ }
++
++ break;
++ }
++ case sol::Parameter::port:
++ {
++ return ipmi::responseSystemInfoParameterSetReadOnly();
++ }
++ case sol::Parameter::nvbitrate:
++ case sol::Parameter::vbitrate:
++ case sol::Parameter::channel:
++ default:
++ return ipmi::responseParmNotSupported();
++ }
++
++ return ipmi::responseSuccess();
++}
++
+ void register_netfn_transport_functions()
+ {
+ ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnTransport,
+@@ -1178,4 +1493,11 @@ void register_netfn_transport_functions()
+ ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnTransport,
+ ipmi::transport::cmdGetLanConfigParameters,
+ ipmi::Privilege::Admin, ipmi::transport::getLan);
++
++ ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnTransport,
++ ipmi::transport::cmdSetSolConfigParameters,
++ ipmi::Privilege::Admin, setSOLConfParams);
++
++ // Initialize dbus property progress to 0 every time sol manager restart.
++ initializeSOLInProgress();
+ }
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0060-Move-Get-SOL-config-parameter-to-host-ipmid.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0060-Move-Get-SOL-config-parameter-to-host-ipmid.patch
new file mode 100644
index 000000000..01a3e49b8
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0060-Move-Get-SOL-config-parameter-to-host-ipmid.patch
@@ -0,0 +1,260 @@
+From e8ad148601fc3b45fac9092fdd45c537433e662f Mon Sep 17 00:00:00 2001
+From: Cheng C Yang <cheng.c.yang@intel.com>
+Date: Thu, 11 Jul 2019 00:32:58 +0800
+Subject: [PATCH] Move Get SOL config parameter to host-ipmid
+
+Move Get SOL config parameter command from net-ipmid to host-ipmid.
+
+Tested:
+Run command ipmitool sol info 1
+Set in progress : set-complete
+Enabled : true
+Force Encryption : false
+Force Authentication : false
+Privilege Level : ADMINISTRATOR
+Character Accumulate Level (ms) : 60
+Character Send Threshold : 96
+Retry Count : 6
+Retry Interval (ms) : 200
+Volatile Bit Rate (kbps) : IPMI-Over-Serial-Setting
+Non-Volatile Bit Rate (kbps) : 115.2
+Payload Channel : 1 (0x01)
+Payload Port : 623
+
+Signed-off-by: Cheng C Yang <cheng.c.yang@intel.com>
+---
+ host-ipmid-whitelist.conf | 1 +
+ transporthandler.cpp | 191 ++++++++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 192 insertions(+)
+
+diff --git a/host-ipmid-whitelist.conf b/host-ipmid-whitelist.conf
+index 44c2181..0fcac4e 100644
+--- a/host-ipmid-whitelist.conf
++++ b/host-ipmid-whitelist.conf
+@@ -41,6 +41,7 @@
+ 0x0A:0x49 //<Storage>:<Set SEL Time>
+ 0x0C:0x02 //<Transport>:<Get LAN Configuration Parameters>
+ 0x0C:0x21 //<Transport>:<Set SOL Configuration Parameters>
++0x0C:0x22 //<Transport>:<Get SOL Configuration Parameters>
+ 0x2C:0x00 //<Group Extension>:<Group Extension Command>
+ 0x2C:0x01 //<Group Extension>:<Get DCMI Capabilities>
+ 0x2C:0x02 //<Group Extension>:<Get Power Reading>
+diff --git a/transporthandler.cpp b/transporthandler.cpp
+index 25062ae..9ba2868 100644
+--- a/transporthandler.cpp
++++ b/transporthandler.cpp
+@@ -1719,6 +1719,28 @@ static int getSOLParameter(const std::string& property, ipmi::Value& value,
+ return 0;
+ }
+
++constexpr const char* consoleInterface = "xyz.openbmc_project.console";
++constexpr const char* consolePath = "/xyz/openbmc_project/console";
++static int getSOLBaudRate(ipmi::Value& value)
++{
++ auto dbus = getSdBus();
++
++ try
++ {
++ value =
++ ipmi::getDbusProperty(*dbus, "xyz.openbmc_project.console",
++ consolePath, consoleInterface, "baudrate");
++ }
++ catch (sdbusplus::exception_t&)
++ {
++ phosphor::logging::log<phosphor::logging::level::ERR>(
++ "Error getting sol baud rate");
++ return -1;
++ }
++
++ return 0;
++}
++
+ void initializeSOLInProgress()
+ {
+ ipmi::ChannelInfo chInfo;
+@@ -1913,6 +1935,171 @@ ipmi::RspType<> setSOLConfParams(ipmi::Context::ptr ctx, uint4_t chNum,
+ return ipmi::responseSuccess();
+ }
+
++static const constexpr uint8_t retryCountMask = 0x07;
++static constexpr uint16_t ipmiStdPort = 623;
++static constexpr uint8_t solParameterRevision = 0x11;
++ipmi::RspType<uint8_t, std::optional<uint8_t>, std::optional<uint8_t>>
++ getSOLConfParams(ipmi::Context::ptr ctx, uint4_t chNum, uint3_t reserved,
++ bool getParamRev, uint8_t paramSelector,
++ uint8_t setSelector, uint8_t blockSelector)
++{
++ ipmi::ChannelInfo chInfo;
++ uint8_t channelNum = ipmi::convertCurrentChannelNum(
++ static_cast<uint8_t>(chNum), ctx->channel);
++ if (reserved != 0 ||
++ (!ipmi::isValidChannel(static_cast<uint8_t>(channelNum))) ||
++ (ipmi::EChannelSessSupported::none ==
++ ipmi::getChannelSessionSupport(static_cast<uint8_t>(channelNum))))
++ {
++ return ipmi::responseInvalidFieldRequest();
++ }
++ ipmi_ret_t compCode =
++ ipmi::getChannelInfo(static_cast<uint8_t>(channelNum), chInfo);
++ if (compCode != IPMI_CC_OK ||
++ chInfo.mediumType !=
++ static_cast<uint8_t>(ipmi::EChannelMediumType::lan8032))
++ {
++ return ipmi::responseInvalidFieldRequest();
++ }
++
++ if (getParamRev)
++ {
++ return ipmi::responseSuccess(solParameterRevision, std::nullopt,
++ std::nullopt);
++ }
++
++ ipmi::Value value;
++ switch (static_cast<sol::Parameter>(paramSelector))
++ {
++ case sol::Parameter::progress:
++ {
++ if (getSOLParameter("Progress", value, channelNum) < 0)
++ {
++ return ipmi::responseUnspecifiedError();
++ }
++ return ipmi::responseSuccess(
++ solParameterRevision, std::get<uint8_t>(value), std::nullopt);
++ }
++ case sol::Parameter::enable:
++ {
++ if (getSOLParameter("Enable", value, channelNum) < 0)
++ {
++ return ipmi::responseUnspecifiedError();
++ }
++ return ipmi::responseSuccess(
++ solParameterRevision,
++ static_cast<uint8_t>(std::get<bool>(value)), std::nullopt);
++ }
++ case sol::Parameter::authentication:
++ {
++ uint8_t authentication = 0;
++ if (getSOLParameter("Privilege", value, channelNum) < 0)
++ {
++ return ipmi::responseUnspecifiedError();
++ }
++ authentication = (std::get<uint8_t>(value) & 0x0f);
++
++ if (getSOLParameter("ForceAuthentication", value, channelNum) < 0)
++ {
++ return ipmi::responseUnspecifiedError();
++ }
++ authentication |=
++ (static_cast<uint8_t>(std::get<bool>(value)) << 6);
++
++ if (getSOLParameter("ForceEncryption", value, channelNum) < 0)
++ {
++ return ipmi::responseUnspecifiedError();
++ }
++ authentication |=
++ (static_cast<uint8_t>(std::get<bool>(value)) << 7);
++ return ipmi::responseSuccess(solParameterRevision, authentication,
++ std::nullopt);
++ }
++ case sol::Parameter::accumulate:
++ {
++ if (getSOLParameter("AccumulateIntervalMS", value, channelNum) < 0)
++ {
++ return ipmi::responseUnspecifiedError();
++ }
++
++ ipmi::Value value1;
++ if (getSOLParameter("Threshold", value1, channelNum) < 0)
++ {
++ return ipmi::responseUnspecifiedError();
++ }
++ return ipmi::responseSuccess(solParameterRevision,
++ std::get<uint8_t>(value),
++ std::get<uint8_t>(value1));
++ }
++ case sol::Parameter::retry:
++ {
++ if (getSOLParameter("RetryCount", value, channelNum) < 0)
++ {
++ return ipmi::responseUnspecifiedError();
++ }
++
++ ipmi::Value value1;
++ if (getSOLParameter("RetryIntervalMS", value1, channelNum) < 0)
++ {
++ return ipmi::responseUnspecifiedError();
++ }
++ return ipmi::responseSuccess(
++ solParameterRevision, std::get<uint8_t>(value) & retryCountMask,
++ std::get<uint8_t>(value1));
++ }
++ case sol::Parameter::channel:
++ {
++ return ipmi::responseSuccess(solParameterRevision, channelNum,
++ std::nullopt);
++ }
++ case sol::Parameter::port:
++ {
++ uint16_t port = htole16(ipmiStdPort);
++ auto buffer = reinterpret_cast<const uint8_t*>(&port);
++ return ipmi::responseSuccess(solParameterRevision, buffer[0],
++ buffer[1]);
++ }
++ case sol::Parameter::nvbitrate:
++ {
++ if (getSOLBaudRate(value) < 0)
++ {
++ return ipmi::responseUnspecifiedError();
++ }
++ uint8_t bitRate = 0;
++ uint32_t* pBaudRate = std::get_if<uint32_t>(&value);
++ if (!pBaudRate)
++ {
++ phosphor::logging::log<phosphor::logging::level::ERR>(
++ "Failed to get valid baud rate from D-Bus interface");
++ }
++ switch (*pBaudRate)
++ {
++ case 9600:
++ bitRate = 0x06;
++ break;
++ case 19200:
++ bitRate = 0x07;
++ break;
++ case 38400:
++ bitRate = 0x08;
++ break;
++ case 57600:
++ bitRate = 0x09;
++ break;
++ case 115200:
++ bitRate = 0x0a;
++ break;
++ default:
++ break;
++ }
++ return ipmi::responseSuccess(solParameterRevision, bitRate,
++ std::nullopt);
++ }
++ default:
++ return ipmi::responseParmNotSupported();
++ }
++}
++
+ void register_netfn_transport_functions()
+ {
+ // As this timer is only for transport handler
+@@ -1934,6 +2121,10 @@ void register_netfn_transport_functions()
+ ipmi::transport::cmdSetSolConfigParameters,
+ ipmi::Privilege::Admin, setSOLConfParams);
+
++ ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnTransport,
++ ipmi::transport::cmdGetSolConfigParameters,
++ ipmi::Privilege::User, getSOLConfParams);
++
+ // Initialize dbus property progress to 0 every time sol manager restart.
+ initializeSOLInProgress();
+
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0062-Update-IPMI-Chassis-Control-command.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0062-Update-IPMI-Chassis-Control-command.patch
new file mode 100644
index 000000000..f29111758
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0062-Update-IPMI-Chassis-Control-command.patch
@@ -0,0 +1,289 @@
+From 00fb92edcb4229eeb5b46c4eb206ba7d70e241fc Mon Sep 17 00:00:00 2001
+From: "Jason M. Bills" <jason.m.bills@linux.intel.com>
+Date: Mon, 3 Jun 2019 17:01:47 -0700
+Subject: [PATCH] Update IPMI Chassis Control command
+
+This change updates the IPMI Chassis Control command to use the new
+chassis state transitions. This allows each chassis control action
+to more closely follow the behavior defined in the IPMI spec.
+
+Tested:
+Ran each IPMI chassis control command to confirm the expected
+behavior:
+ipmitool power on: system is powered-on
+ipmitool power off: system is forced off
+ipmitool power cycle: system is forced off then powered-on
+ipmitool power reset: system is hard reset
+ipmitool power soft: soft power-off requested from system software
+
+Change-Id: Ic9fba3ca4abd9a758eb88f1e6ee09f7ca64ff80a
+Signed-off-by: Jason M. Bills <jason.m.bills@linux.intel.com>
+---
+ chassishandler.cpp | 206 ++++++++++++++---------------------------------------
+ 1 file changed, 52 insertions(+), 154 deletions(-)
+
+diff --git a/chassishandler.cpp b/chassishandler.cpp
+index 88bf84b..ad564e2 100644
+--- a/chassishandler.cpp
++++ b/chassishandler.cpp
+@@ -31,6 +31,7 @@
+ #include <xyz/openbmc_project/Control/Boot/Mode/server.hpp>
+ #include <xyz/openbmc_project/Control/Boot/Source/server.hpp>
+ #include <xyz/openbmc_project/Control/Power/RestorePolicy/server.hpp>
++#include <xyz/openbmc_project/State/Chassis/server.hpp>
+ #include <xyz/openbmc_project/State/Host/server.hpp>
+ #include <xyz/openbmc_project/State/PowerOnHours/server.hpp>
+
+@@ -712,59 +713,63 @@ ipmi_ret_t ipmi_set_chassis_cap(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+ //------------------------------------------
+ // Calls into Host State Manager Dbus object
+ //------------------------------------------
+-int initiate_state_transition(State::Host::Transition transition)
++int initiateHostStateTransition(State::Host::Transition transition)
+ {
+ // OpenBMC Host State Manager dbus framework
+- constexpr auto HOST_STATE_MANAGER_ROOT = "/xyz/openbmc_project/state/host0";
+- constexpr auto HOST_STATE_MANAGER_IFACE = "xyz.openbmc_project.State.Host";
+- constexpr auto DBUS_PROPERTY_IFACE = "org.freedesktop.DBus.Properties";
+- constexpr auto PROPERTY = "RequestedHostTransition";
++ constexpr auto hostStatePath = "/xyz/openbmc_project/state/host0";
++ constexpr auto hostStateIntf = "xyz.openbmc_project.State.Host";
+
+- // sd_bus error
+- int rc = 0;
+- char* busname = NULL;
++ auto service = ipmi::getService(*getSdBus(), hostStateIntf, hostStatePath);
+
+- // SD Bus error report mechanism.
+- sd_bus_error bus_error = SD_BUS_ERROR_NULL;
++ // Convert to string equivalent of the passed in transition enum.
++ auto request = State::convertForMessage(transition);
+
+- // Gets a hook onto either a SYSTEM or SESSION bus
+- sd_bus* bus_type = ipmid_get_sd_bus_connection();
+- rc = mapper_get_service(bus_type, HOST_STATE_MANAGER_ROOT, &busname);
+- if (rc < 0)
++ try
++ {
++ ipmi::setDbusProperty(*getSdBus(), service, hostStatePath,
++ hostStateIntf, "RequestedHostTransition",
++ request);
++ }
++ catch (std::exception& e)
+ {
+ log<level::ERR>(
+- "Failed to get bus name",
+- entry("ERRNO=0x%X, OBJPATH=%s", -rc, HOST_STATE_MANAGER_ROOT));
+- return rc;
++ "Failed to initiate transition",
++ entry("EXCEPTION=%s, REQUEST=%s", e.what(), request.c_str()));
++ return -1;
+ }
++ return 0;
++}
++
++//------------------------------------------
++// Calls into Chassis State Manager Dbus object
++//------------------------------------------
++int initiateChassisStateTransition(State::Chassis::Transition transition)
++{
++ // OpenBMC Chassis State Manager dbus framework
++ constexpr auto chassisStatePath = "/xyz/openbmc_project/state/chassis0";
++ constexpr auto chassisStateIntf = "xyz.openbmc_project.State.Chassis";
++
++ auto service =
++ ipmi::getService(*getSdBus(), chassisStateIntf, chassisStatePath);
+
+ // Convert to string equivalent of the passed in transition enum.
+ auto request = State::convertForMessage(transition);
+
+- rc = sd_bus_call_method(bus_type, // On the system bus
+- busname, // Service to contact
+- HOST_STATE_MANAGER_ROOT, // Object path
+- DBUS_PROPERTY_IFACE, // Interface name
+- "Set", // Method to be called
+- &bus_error, // object to return error
+- nullptr, // Response buffer if any
+- "ssv", // Takes 3 arguments
+- HOST_STATE_MANAGER_IFACE, PROPERTY, "s",
+- request.c_str());
+- if (rc < 0)
++ try
+ {
+- log<level::ERR>("Failed to initiate transition",
+- entry("ERRNO=0x%X, REQUEST=%s", -rc, request.c_str()));
++ ipmi::setDbusProperty(*getSdBus(), service, chassisStatePath,
++ chassisStateIntf, "RequestedPowerTransition",
++ request);
+ }
+- else
++ catch (std::exception& e)
+ {
+- log<level::INFO>("Transition request initiated successfully");
++ log<level::ERR>(
++ "Failed to initiate transition",
++ entry("EXCEPTION=%s, REQUEST=%s", e.what(), request.c_str()));
++ return -1;
+ }
+
+- sd_bus_error_free(&bus_error);
+- free(busname);
+-
+- return rc;
++ return 0;
+ }
+
+ namespace power_policy
+@@ -1033,76 +1038,6 @@ ipmi::RspType<bool, // Power is on
+ diagButtonDisableAllow, sleepButtonDisableAllow);
+ }
+
+-//-------------------------------------------------------------
+-// Send a command to SoftPowerOff application to stop any timer
+-//-------------------------------------------------------------
+-int stop_soft_off_timer()
+-{
+- constexpr auto iface = "org.freedesktop.DBus.Properties";
+- constexpr auto soft_off_iface = "xyz.openbmc_project.Ipmi.Internal."
+- "SoftPowerOff";
+-
+- constexpr auto property = "ResponseReceived";
+- constexpr auto value = "xyz.openbmc_project.Ipmi.Internal."
+- "SoftPowerOff.HostResponse.HostShutdown";
+-
+- // Get the system bus where most system services are provided.
+- auto bus = ipmid_get_sd_bus_connection();
+-
+- // Get the service name
+- // TODO openbmc/openbmc#1661 - Mapper refactor
+- //
+- // See openbmc/openbmc#1743 for some details but high level summary is that
+- // for now the code will directly call the soft off interface due to a
+- // race condition with mapper usage
+- //
+- // char *busname = nullptr;
+- // auto r = mapper_get_service(bus, SOFTOFF_OBJPATH, &busname);
+- // if (r < 0)
+- //{
+- // fprintf(stderr, "Failed to get %s bus name: %s\n",
+- // SOFTOFF_OBJPATH, -r);
+- // return r;
+- //}
+-
+- // No error object or reply expected.
+- int rc = sd_bus_call_method(bus, SOFTOFF_BUSNAME, SOFTOFF_OBJPATH, iface,
+- "Set", nullptr, nullptr, "ssv", soft_off_iface,
+- property, "s", value);
+- if (rc < 0)
+- {
+- log<level::ERR>("Failed to set property in SoftPowerOff object",
+- entry("ERRNO=0x%X", -rc));
+- }
+-
+- // TODO openbmc/openbmc#1661 - Mapper refactor
+- // free(busname);
+- return rc;
+-}
+-
+-//----------------------------------------------------------------------
+-// Create file to indicate there is no need for softoff notification to host
+-//----------------------------------------------------------------------
+-void indicate_no_softoff_needed()
+-{
+- fs::path path{HOST_INBAND_REQUEST_DIR};
+- if (!fs::is_directory(path))
+- {
+- fs::create_directory(path);
+- }
+-
+- // Add the host instance (default 0 for now) to the file name
+- std::string file{HOST_INBAND_REQUEST_FILE};
+- auto size = std::snprintf(nullptr, 0, file.c_str(), 0);
+- size++; // null
+- std::unique_ptr<char[]> buf(new char[size]);
+- std::snprintf(buf.get(), size, file.c_str(), 0);
+-
+- // Append file name to directory and create it
+- path /= buf.get();
+- std::ofstream(path.c_str());
+-}
+-
+ /** @brief Implementation of chassis control command
+ *
+ * @param - chassisControl command byte
+@@ -1115,61 +1050,24 @@ ipmi::RspType<> ipmiChassisControl(uint8_t chassisControl)
+ switch (chassisControl)
+ {
+ case CMD_POWER_ON:
+- rc = initiate_state_transition(State::Host::Transition::On);
++ rc = initiateHostStateTransition(State::Host::Transition::On);
+ break;
+ case CMD_POWER_OFF:
+- // This path would be hit in 2 conditions.
+- // 1: When user asks for power off using ipmi chassis command 0x04
+- // 2: Host asking for power off post shutting down.
+-
+- // If it's a host requested power off, then need to nudge Softoff
+- // application that it needs to stop the watchdog timer if running.
+- // If it is a user requested power off, then this is not really
+- // needed. But then we need to differentiate between user and host
+- // calling this same command
+-
+- // For now, we are going ahead with trying to nudge the soft off and
+- // interpret the failure to do so as a non softoff case
+- rc = stop_soft_off_timer();
+-
+- // Only request the Off transition if the soft power off
+- // application is not running
+- if (rc < 0)
+- {
+- // First create a file to indicate to the soft off application
+- // that it should not run. Not doing this will result in State
+- // manager doing a default soft power off when asked for power
+- // off.
+- indicate_no_softoff_needed();
+-
+- // Now request the shutdown
+- rc = initiate_state_transition(State::Host::Transition::Off);
+- }
+- else
+- {
+- log<level::INFO>("Soft off is running, so let shutdown target "
+- "stop the host");
+- }
++ rc =
++ initiateChassisStateTransition(State::Chassis::Transition::Off);
+ break;
+-
+ case CMD_HARD_RESET:
++ rc = initiateChassisStateTransition(
++ State::Chassis::Transition::Reset);
++ break;
+ case CMD_POWER_CYCLE:
+- // SPEC has a section that says certain implementations can trigger
+- // PowerOn if power is Off when a command to power cycle is
+- // requested
+-
+- // First create a file to indicate to the soft off application
+- // that it should not run since this is a direct user initiated
+- // power reboot request (i.e. a reboot request that is not
+- // originating via a soft power off SMS request)
+- indicate_no_softoff_needed();
+-
+- rc = initiate_state_transition(State::Host::Transition::Reboot);
++ rc = initiateChassisStateTransition(
++ State::Chassis::Transition::PowerCycle);
+ break;
+-
+ case CMD_SOFT_OFF_VIA_OVER_TEMP:
+- // Request Host State Manager to do a soft power off
+- rc = initiate_state_transition(State::Host::Transition::Off);
++ rc = initiateHostStateTransition(State::Host::Transition::Off);
++ break;
++ case CMD_PULSE_DIAGNOSTIC_INTR:
+ break;
+
+ default:
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0063-Save-the-pre-timeout-interrupt-in-dbus-property.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0063-Save-the-pre-timeout-interrupt-in-dbus-property.patch
new file mode 100644
index 000000000..aac0850ea
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0063-Save-the-pre-timeout-interrupt-in-dbus-property.patch
@@ -0,0 +1,140 @@
+From d9c89943d7b0aa00ee99b7c11278ac272a47a790 Mon Sep 17 00:00:00 2001
+From: Ren Yu <yux.ren@intel.com>
+Date: Tue, 28 May 2019 17:11:17 +0800
+Subject: [PATCH] Save the pre-timeout interrupt in dbus property
+
+Get the watchdog pre-timeout interrupt value from ipmi watchdog set command,
+and store it into dbus property.
+
+Tested:
+Config IPMI watchdog: BIOS FRB2 Power Cycle after 1 seconds:
+ipmitool raw 0x06 0x24 0x01 0x13 0x0 0x2 0xa 0x00
+Start watchdog:
+Ipmitool mc watchdog reset
+Check the watchdog pre-timeout interrupt in below:
+https://BMCIP/redfish/v1/Systems/system/LogServices/EventLog/Entries
+
+Signed-off-by: Ren Yu <yux.ren@intel.com>
+---
+ app/watchdog.cpp | 47 +++++++++++++++++++++++++++++++++++++++++++++++
+ app/watchdog_service.cpp | 6 ++++++
+ app/watchdog_service.hpp | 9 +++++++++
+ 3 files changed, 62 insertions(+)
+
+diff --git a/app/watchdog.cpp b/app/watchdog.cpp
+index 2ffaae3..e9b7a9c 100644
+--- a/app/watchdog.cpp
++++ b/app/watchdog.cpp
+@@ -81,6 +81,7 @@ ipmi::RspType<> ipmiAppResetWatchdogTimer()
+
+ static constexpr uint8_t wd_dont_stop = 0x1 << 6;
+ static constexpr uint8_t wd_timeout_action_mask = 0x3;
++static constexpr uint8_t wdPreTimeoutInterruptMask = 0x3;
+
+ static constexpr uint8_t wdTimerUseMask = 0x7;
+ static constexpr uint8_t wdTimerUseResTimer1 = 0x0;
+@@ -130,6 +131,45 @@ WatchdogService::Action ipmiActionToWdAction(IpmiAction ipmi_action)
+ }
+ }
+
++enum class IpmiPreTimeoutInterrupt : uint8_t
++{
++ None = 0x0,
++ SMI = 0x1,
++ NMI = 0x2,
++ MI = 0x3,
++};
++/** @brief Converts an IPMI Watchdog PreTimeoutInterrupt to DBUS defined action
++ * @param[in] ipmi_action The IPMI Watchdog PreTimeoutInterrupt
++ * @return The Watchdog PreTimeoutInterrupt that the ipmi_action maps to
++ */
++WatchdogService::PreTimeoutInterruptAction ipmiPreTimeoutInterruptToWdAction(
++ IpmiPreTimeoutInterrupt ipmiPreTimeOutInterrupt)
++{
++ switch (ipmiPreTimeOutInterrupt)
++ {
++ case IpmiPreTimeoutInterrupt::None:
++ {
++ return WatchdogService::PreTimeoutInterruptAction::None;
++ }
++ case IpmiPreTimeoutInterrupt::SMI:
++ {
++ return WatchdogService::PreTimeoutInterruptAction::SMI;
++ }
++ case IpmiPreTimeoutInterrupt::NMI:
++ {
++ return WatchdogService::PreTimeoutInterruptAction::NMI;
++ }
++ case IpmiPreTimeoutInterrupt::MI:
++ {
++ return WatchdogService::PreTimeoutInterruptAction::MI;
++ }
++ default:
++ {
++ throw std::domain_error("IPMI PreTimeoutInterrupt is invalid");
++ }
++ }
++}
++
+ enum class IpmiTimerUse : uint8_t
+ {
+ Reserved = 0x0,
+@@ -257,6 +297,13 @@ ipmi_ret_t ipmi_app_watchdog_set(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+ // Mark as initialized so that future resets behave correctly
+ wd_service.setInitialized(true);
+
++ // pretimeOutAction
++ const auto ipmiPreTimeoutInterrupt =
++ static_cast<IpmiPreTimeoutInterrupt>(wdPreTimeoutInterruptMask &
++ (static_cast<uint8_t>(preTimeoutInterrupt)));
++ wd_service.setPreTimeoutInterrupt(
++ ipmiPreTimeoutInterruptToWdAction(ipmiPreTimeoutInterrupt));
++
+ lastCallSuccessful = true;
+ return IPMI_CC_OK;
+ }
+diff --git a/app/watchdog_service.cpp b/app/watchdog_service.cpp
+index 77663b4..0c4ea28 100644
+--- a/app/watchdog_service.cpp
++++ b/app/watchdog_service.cpp
+@@ -203,3 +203,9 @@ void WatchdogService::setTimeRemaining(uint64_t timeRemaining)
+ {
+ setProperty("TimeRemaining", timeRemaining);
+ }
++
++void WatchdogService::setPreTimeoutInterrupt(
++ PreTimeoutInterruptAction preTimeoutInterrupt)
++{
++ setProperty("PreTimeoutInterrupt", convertForMessage(preTimeoutInterrupt));
++}
+\ No newline at end of file
+diff --git a/app/watchdog_service.hpp b/app/watchdog_service.hpp
+index ed64a3c..b550f37 100644
+--- a/app/watchdog_service.hpp
++++ b/app/watchdog_service.hpp
+@@ -15,6 +15,8 @@ class WatchdogService
+
+ using Action =
+ sdbusplus::xyz::openbmc_project::State::server::Watchdog::Action;
++ using PreTimeoutInterruptAction = sdbusplus::xyz::openbmc_project::State::
++ server::Watchdog::PreTimeoutInterruptAction;
+ using TimerUse =
+ sdbusplus::xyz::openbmc_project::State::server::Watchdog::TimerUse;
+
+@@ -99,6 +101,13 @@ class WatchdogService
+ */
+ void setTimeRemaining(uint64_t timeRemaining);
+
++ /** @brief Sets the value of the PreTimeoutInterrupt property on the host
++ * watchdog
++ *
++ * @param[in] PreTimeoutInterrupt - The new PreTimeoutInterrupt value
++ */
++ void setPreTimeoutInterrupt(PreTimeoutInterruptAction preTimeoutInterrupt);
++
+ private:
+ /** @brief sdbusplus handle */
+ sdbusplus::bus::bus bus;
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0064-Enable-watchdog-to-save-useflag-after-host-power-off.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0064-Enable-watchdog-to-save-useflag-after-host-power-off.patch
new file mode 100644
index 000000000..4ee28bb5c
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0064-Enable-watchdog-to-save-useflag-after-host-power-off.patch
@@ -0,0 +1,66 @@
+From e7b86ade7db1e9ae86ea39a957bead9090f4ccbf Mon Sep 17 00:00:00 2001
+From: Yong Li <yong.b.li@linux.intel.com>
+Date: Thu, 12 Sep 2019 13:18:42 +0800
+Subject: [PATCH] Enable watchdog to save useflag after host power off
+
+Get the right useflag after host power off.
+
+Tested:
+Set a watchdog (Timer action is none and Time Use is BIOS FRB2)
+ipmitool raw 0x06 0x24 0x01 0x00 0x00 0x00 0x40 0x00
+Get watchdog
+ipmitool mc watchdog get
+Start watchdog
+ipmitool mc watchdog reset
+Get watchdog
+ipmitool mc watchdog get
+After timer is stop, set a watchdog again
+(Timer action is none and Time Use is BIOS/POST)
+ipmitool raw 0x06 0x24 0x02 0x00 0x00 0x00 0x40 0x00
+Start watchdog and wait until timer is stop,
+Get watchdog
+ipmitool mc watchdog get
+Timer Expiration Flags should be 0x06(BIOS FRB2, BIOS/POST)
+Power down the Host
+Ipmitool chassis power off
+Check the Timer Expiration Flags(User Flags)
+ipmitool mc watchdog get
+Timer Expiration Flags should be 0x06(BIOS FRB2, BIOS/POST)
+
+Signed-off-by: Yong Li <yong.b.li@linux.intel.com>
+---
+ app/watchdog.cpp | 4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+diff --git a/app/watchdog.cpp b/app/watchdog.cpp
+index 4650d89..1562f5e 100644
+--- a/app/watchdog.cpp
++++ b/app/watchdog.cpp
+@@ -435,23 +435,21 @@ ipmi::RspType<uint8_t, // timerUse
+ wdTimerUseToIpmiTimerUse(wd_prop.expiredTimerUse));
+ }
+
++ expireFlags = timerUseExpirationFlags;
+ if (wd_prop.enabled)
+ {
+ timerUse |= wd_running;
+ presentCountdown = htole16(wd_prop.timeRemaining / 100);
+- expireFlags = 0;
+ }
+ else
+ {
+ if (wd_prop.expiredTimerUse == WatchdogService::TimerUse::Reserved)
+ {
+ presentCountdown = initialCountdown;
+- expireFlags = 0;
+ }
+ else
+ {
+ presentCountdown = 0;
+- expireFlags = timerUseExpirationFlags;
+ }
+ }
+
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0064-Update-provisioning-mode-filter-logic.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0064-Update-provisioning-mode-filter-logic.patch
new file mode 100644
index 000000000..57a31c991
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0064-Update-provisioning-mode-filter-logic.patch
@@ -0,0 +1,286 @@
+From 3279300bb9afd1f169b35b7830d7f054045ab35f Mon Sep 17 00:00:00 2001
+From: Richard Marian Thomaiyar <richard.marian.thomaiyar@linux.intel.com>
+Date: Tue, 18 Jun 2019 19:42:30 +0530
+Subject: [PATCH] Update provisioning mode filter logic
+
+Updated provisioning mode filtering logic support. Based on the
+RestrictionMode property, Host (system) interface commands will be
+filtered as per the allowed list in ProvisionedHostWhitelist once
+POST complete is achieved. No commands will be allowed in
+ProvisionedHostDisabled after POST complete and in all other cases
+filterning logic will not be applied.
+
+Tested
+1. Verified the filtering logic through EFI shell and made sure
+filtering logic is applied when RestrictionMode is in
+ProvisionedHostWhitelist mode
+2. Verified no filtering logic is applied in normal modes
+3. Made sure BIOS is able to execute commands, which are not in
+whitelist (Note: New whitelist conf is under review).
+
+Change-Id: I7a14e827d70e2d8d6975e600a0fd00e2a790bc22
+Signed-off-by: Richard Marian Thomaiyar <richard.marian.thomaiyar@linux.intel.com>
+---
+ whitelist-filter.cpp | 155 ++++++++++++++++++++++++++++++++++++++++-----------
+ 1 file changed, 122 insertions(+), 33 deletions(-)
+
+diff --git a/whitelist-filter.cpp b/whitelist-filter.cpp
+index 9f1e7c8..2c56087 100644
+--- a/whitelist-filter.cpp
++++ b/whitelist-filter.cpp
+@@ -25,6 +25,7 @@ namespace
+ */
+ class WhitelistFilter
+ {
++
+ public:
+ WhitelistFilter();
+ ~WhitelistFilter() = default;
+@@ -35,17 +36,26 @@ class WhitelistFilter
+
+ private:
+ void postInit();
+- void cacheRestrictedMode();
++ void cacheRestrictedAndPostCompleteMode();
+ void handleRestrictedModeChange(sdbusplus::message::message& m);
++ void handlePostCompleteChange(sdbusplus::message::message& m);
+ ipmi::Cc filterMessage(ipmi::message::Request::ptr request);
+
+- bool restrictedMode = true;
++ sdbusplus::xyz::openbmc_project::Control::Security::server::
++ RestrictionMode::Modes restrictionMode =
++ sdbusplus::xyz::openbmc_project::Control::Security::server::
++ RestrictionMode::Modes::ProvisionedHostWhitelist;
++ bool postCompleted = false;
+ std::shared_ptr<sdbusplus::asio::connection> bus;
+ std::unique_ptr<settings::Objects> objects;
++ std::unique_ptr<settings::Objects> postCompleteObj;
+ std::unique_ptr<sdbusplus::bus::match::match> modeChangeMatch;
++ std::unique_ptr<sdbusplus::bus::match::match> postCompleteMatch;
+
+ static constexpr const char restrictionModeIntf[] =
+ "xyz.openbmc_project.Control.Security.RestrictionMode";
++ static constexpr const char* systemOsStatusIntf =
++ "xyz.openbmc_project.State.OperatingSystem.Status";
+ };
+
+ WhitelistFilter::WhitelistFilter()
+@@ -63,16 +73,22 @@ WhitelistFilter::WhitelistFilter()
+ post_work([this]() { postInit(); });
+ }
+
+-void WhitelistFilter::cacheRestrictedMode()
++void WhitelistFilter::cacheRestrictedAndPostCompleteMode()
+ {
+ using namespace sdbusplus::xyz::openbmc_project::Control::Security::server;
+ std::string restrictionModeSetting;
+ std::string restrictionModeService;
++ std::string systemOsStatusPath;
++ std::string systemOsStatusService;
+ try
+ {
+ restrictionModeSetting = objects->map.at(restrictionModeIntf).at(0);
+ restrictionModeService =
+ objects->service(restrictionModeSetting, restrictionModeIntf);
++
++ systemOsStatusPath = postCompleteObj->map.at(systemOsStatusIntf).at(0);
++ systemOsStatusService =
++ postCompleteObj->service(systemOsStatusPath, systemOsStatusIntf);
+ }
+ catch (const std::out_of_range& e)
+ {
+@@ -80,26 +96,50 @@ void WhitelistFilter::cacheRestrictedMode()
+ "Could not look up restriction mode interface from cache");
+ return;
+ }
++
+ bus->async_method_call(
+ [this](boost::system::error_code ec, ipmi::Value v) {
+ if (ec)
+ {
+ log<level::ERR>("Error in RestrictionMode Get");
+ // Fail-safe to true.
+- restrictedMode = true;
++ restrictionMode =
++ RestrictionMode::Modes::ProvisionedHostWhitelist;
+ return;
+ }
+ auto mode = std::get<std::string>(v);
+- auto restrictionMode =
+- RestrictionMode::convertModesFromString(mode);
+- restrictedMode =
+- (restrictionMode == RestrictionMode::Modes::Whitelist);
+- log<level::INFO>((restrictedMode ? "Set restrictedMode = true"
+- : "Set restrictedMode = false"));
++ restrictionMode = RestrictionMode::convertModesFromString(mode);
++ log<level::INFO>(
++ "Read restriction mode",
++ entry("VALUE=%d", static_cast<int>(restrictionMode)));
+ },
+ restrictionModeService, restrictionModeSetting,
+ "org.freedesktop.DBus.Properties", "Get", restrictionModeIntf,
+ "RestrictionMode");
++
++ bus->async_method_call(
++ [this](boost::system::error_code ec, const ipmi::Value& v) {
++ if (ec)
++ {
++ log<level::ERR>("Error in OperatingSystemState Get");
++ postCompleted = true;
++ return;
++ }
++ auto value = std::get<std::string>(v);
++ if (value == "Standby")
++ {
++ postCompleted = true;
++ }
++ else
++ {
++ postCompleted = false;
++ }
++ log<level::INFO>("Read POST complete value",
++ entry("VALUE=%d", postCompleted));
++ },
++ systemOsStatusService, systemOsStatusPath,
++ "org.freedesktop.DBus.Properties", "Get", systemOsStatusIntf,
++ "OperatingSystemState");
+ }
+
+ void WhitelistFilter::handleRestrictedModeChange(sdbusplus::message::message& m)
+@@ -112,23 +152,44 @@ void WhitelistFilter::handleRestrictedModeChange(sdbusplus::message::message& m)
+ {
+ if (property.first == "RestrictionMode")
+ {
+- RestrictionMode::Modes restrictionMode =
+- RestrictionMode::convertModesFromString(
+- std::get<std::string>(property.second));
+- restrictedMode =
+- (restrictionMode == RestrictionMode::Modes::Whitelist);
+- log<level::INFO>((restrictedMode
+- ? "Updated restrictedMode = true"
+- : "Updated restrictedMode = false"));
++ restrictionMode = RestrictionMode::convertModesFromString(
++ std::get<std::string>(property.second));
++ log<level::INFO>(
++ "Updated restriction mode",
++ entry("VALUE=%d", static_cast<int>(restrictionMode)));
++ }
++ }
++}
++void WhitelistFilter::handlePostCompleteChange(sdbusplus::message::message& m)
++{
++ std::string intf;
++ std::vector<std::pair<std::string, ipmi::Value>> propertyList;
++ m.read(intf, propertyList);
++ for (const auto& property : propertyList)
++ {
++ if (property.first == "OperatingSystemState")
++ {
++ std::string value = std::get<std::string>(property.second);
++ if (value == "Standby")
++ {
++ postCompleted = true;
++ }
++ else
++ {
++ postCompleted = false;
++ }
++ log<level::INFO>(postCompleted ? "Updated to POST Complete"
++ : "Updated to !POST Complete");
+ }
+ }
+ }
+-
+ void WhitelistFilter::postInit()
+ {
+ objects = std::make_unique<settings::Objects>(
+ *bus, std::vector<settings::Interface>({restrictionModeIntf}));
+- if (!objects)
++ postCompleteObj = std::make_unique<settings::Objects>(
++ *bus, std::vector<settings::Interface>({systemOsStatusIntf}));
++ if (!objects || !postCompleteObj)
+ {
+ log<level::ERR>(
+ "Failed to create settings object; defaulting to restricted mode");
+@@ -136,37 +197,65 @@ void WhitelistFilter::postInit()
+ }
+
+ // Initialize restricted mode
+- cacheRestrictedMode();
++ cacheRestrictedAndPostCompleteMode();
+ // Wait for changes on Restricted mode
+- std::string filterStr;
++ std::string filterStrModeChange;
++ std::string filterStrPostComplete;
+ try
+ {
+- filterStr = sdbusplus::bus::match::rules::propertiesChanged(
++ filterStrModeChange = sdbusplus::bus::match::rules::propertiesChanged(
+ objects->map.at(restrictionModeIntf).at(0), restrictionModeIntf);
++ filterStrPostComplete = sdbusplus::bus::match::rules::propertiesChanged(
++ postCompleteObj->map.at(systemOsStatusIntf).at(0),
++ systemOsStatusIntf);
+ }
+ catch (const std::out_of_range& e)
+ {
+- log<level::ERR>("Failed to determine restriction mode filter string");
++ log<level::ERR>("Failed to determine restriction mode / POST complete "
++ "filter string");
+ return;
+ }
+ modeChangeMatch = std::make_unique<sdbusplus::bus::match::match>(
+- *bus, filterStr, [this](sdbusplus::message::message& m) {
++ *bus, filterStrModeChange, [this](sdbusplus::message::message& m) {
+ handleRestrictedModeChange(m);
+ });
++ postCompleteMatch = std::make_unique<sdbusplus::bus::match::match>(
++ *bus, filterStrPostComplete, [this](sdbusplus::message::message& m) {
++ handlePostCompleteChange(m);
++ });
+ }
+
+ ipmi::Cc WhitelistFilter::filterMessage(ipmi::message::Request::ptr request)
+ {
+- if (request->ctx->channel == ipmi::channelSystemIface && restrictedMode)
++ using namespace sdbusplus::xyz::openbmc_project::Control::Security::server;
++
++ if (request->ctx->channel == ipmi::channelSystemIface &&
++ (restrictionMode != RestrictionMode::Modes::None &&
++ restrictionMode != RestrictionMode::Modes::Provisioning))
+ {
+- if (!std::binary_search(
+- whitelist.cbegin(), whitelist.cend(),
+- std::make_pair(request->ctx->netFn, request->ctx->cmd)))
++ if (!postCompleted)
+ {
+- log<level::ERR>("Net function not whitelisted",
+- entry("NETFN=0x%X", int(request->ctx->netFn)),
+- entry("CMD=0x%X", int(request->ctx->cmd)));
+- return ipmi::ccInsufficientPrivilege;
++ // Allow all commands, till POST is not completed
++ return ipmi::ccSuccess;
++ }
++ switch (restrictionMode)
++ {
++ case RestrictionMode::Modes::ProvisionedHostWhitelist:
++ {
++ if (!std::binary_search(
++ whitelist.cbegin(), whitelist.cend(),
++ std::make_pair(request->ctx->netFn, request->ctx->cmd)))
++ {
++ log<level::ERR>(
++ "Net function not whitelisted",
++ entry("NETFN=0x%X", int(request->ctx->netFn)),
++ entry("CMD=0x%X", int(request->ctx->cmd)));
++ return ipmi::ccInsufficientPrivilege;
++ }
++ break;
++ }
++ default: // for whitelist, blacklist & HostDisabled
++ return ipmi::ccInsufficientPrivilege;
+ }
+ }
+ return ipmi::ccSuccess;
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/host-ipmid-whitelist.conf b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/host-ipmid-whitelist.conf
new file mode 100644
index 000000000..f3218d8d8
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/host-ipmid-whitelist.conf
@@ -0,0 +1,196 @@
+#<NetFn>:<Command>
+#IPMI whitelist command list version 9b
+0x00:0x00 //<Chassis>:<Get Chassis Capabiliti>
+0x00:0x01 //<Chassis>:<Get Chassis Status>
+0x00:0x04 //<Chassis>:<Chassis Identify>
+0x00:0x07 //<Chassis>:<Get System Restart Cause>
+0x00:0x09 //<Chassis>:<Get System Boot Options>
+0x00:0x0A //<Chassis>:<Set Front Panel Enables>
+0x00:0x0F //<Chassis>:<Get POH Counter>
+0x04:0x01 //<Sensor/Event>:<Get Event Receiver>
+0x04:0x02 //<Sensor/Event>:<SEL Platform event>
+0x04:0x10 //<Sensor/Event>:<PEF Get Capabilities>
+0x04:0x13 //<Sensor/Event>:<PEF Get Configuration Parameters>
+0x04:0x15 //<Sensor/Event>:<PEF Get Processed EventID>
+0x04:0x20 //<Sensor/Event>:<Get Device SDR Info>
+0x04:0x21 //<Sensor/Event>:<Get Device SDR>
+0x04:0x23 //<Sensor/Event>:<Get Sensor Reading Factors>
+0x04:0x25 //<Sensor/Event>:<Get Sensor Hysteresis>
+0x04:0x27 //<Sensor/Event>:<Get Sensor Threshold>
+0x04:0x29 //<Sensor/Event>:<Get SensorEvent Enable>
+0x04:0x2B //<Sensor/Event>:<Get SensorEvent Status>
+0x04:0x2D //<Sensor/Event>:<Get SensorReading>
+0x04:0x2F //<Sensor/Event>:<Get Sensor Type>
+0x06:0x01 //<App>:<Get Device ID>
+0x06:0x04 //<App>:<Get Self Test>
+0x06:0x06 //<App>:<Set ACPI Power State>
+0x06:0x07 //<App>:<Get ACPI Power State>
+0x06:0x08 //<App>:<Get Device GUID>
+0x06:0x22 //<App>:<Reset Watchdog Timer>
+0x06:0x24 //<App>:<Set Watchdog Timer>
+0x06:0x25 //<App>:<Get Watchdog Timer>
+0x06:0x2F //<App>:<Get BMC Global Enables>
+0x06:0x30 //<App>:<Clear Message Flags>
+0x06:0x31 //<App>:<Get Message Flags>
+0x06:0x33 //<App>:<Get Message>
+0x06:0x35 //<App>:<Read Event Message Buffer>
+0x06:0x37 //<App>:<Get System GUID>
+0x06:0x38 //<App>:<Get Channel Authentication Capability>
+0x06:0x39 //<App>:<Get Session Challenge>
+0x06:0x3D //<App>:<Get Channel Session Info>
+0x06:0x3F //<App>:<Get Authentication Code>
+0x06:0x41 //<App>:<Get Channel Access>
+0x06:0x42 //<App>:<Get Channel Info>
+0x06:0x44 //<App>:<Get User Access>
+0x06:0x46 //<App>:<Get User Name>
+0x06:0x4A //<App>:<Get Payload Activation Status>
+0x06:0x4B //<App>:<Get Payload Instance Info>
+0x06:0x4D //<App>:<Get User Payload Access>
+0x06:0x4E //<App>:<Get Channel Payload Support>
+0x06:0x4F //<App>:<Get Channel Payload Version>
+0x06:0x50 //<App>:<Get Channel OEM Payload Info>
+0x06:0x54 //<App>:<Get Channel Cipher Suites>
+0x06:0x57 //<App>:<Get System Interface Capabilities>
+0x08:0x20 //<Firmware>:<Get Version Information>
+0x08:0x21 //<Firmware>:<Security Version Information>
+0x08:0x22 //<Firmware>:<Firmware Update Channel Information>
+0x08:0x23 //<Firmware>:<BMC Execution Context>
+0x08:0x24 //<Firmware>:<Get Boot Certificate Info>
+0x08:0x25 //<Firmware>:<Get Boot Certificate Data>
+0x08:0x26 //<Firmware>:<Firmware Random Number Update>
+0x08:0x27 //<Firmware>:<Set Firmware Update Mode>
+0x08:0x28 //<Firmware>:<Exit Firmware Update Mode>
+0x08:0x29 //<Firmware>:<Firmware Update Control>
+0x08:0x2A //<Firmware>:<Get Firmware Update Status>
+0x08:0x2B //<Firmware>:<Set Firmware Update Options>
+0x08:0x2C //<Firmware>:<Write Firmware Image>
+0x08:0x2D //<Firmware>:<Get Firmware Update Status Code Message>
+0x08:0xE0 //<Firmware>:<Get Firmware Update Error Code Message>
+0x0A:0x10 //<Storage>:<Get FRU Inventory Area Info>
+0x0A:0x11 //<Storage>:<Read FRU Data>
+0x0A:0x20 //<Storage>:<Get SDR Repository Info>
+0x0A:0x21 //<Storage>:<Get SDR Alloc Info>
+0x0A:0x23 //<Storage>:<Get SDR>
+0x0A:0x28 //<Storage>:<SEL Get Time>
+0x0A:0x40 //<Storage>:<Get SEL Info>
+0x0A:0x41 //<Storage>:<Get SEL Alloc Info>
+0x0A:0x43 //<Storage>:<Get SEL Entry>
+0x0A:0x48 //<Storage>:<Get SEL Time>
+0x0A:0x5A //<Storage>:<Get SEL Auxiliary Log Status>
+0x0A:0x5C //<Storage>:<Get SEL Time UTC Offset>
+0x0C:0x02 //<Transport>:<Get LAN Configuration Parameters>
+0x0C:0x04 //<Transport>:<Get IPUDPRMCP Statistics>
+0x0C:0x11 //<Transport>:<Get Serial Modem Configuration>
+0x0C:0x22 //<Transport>:<Get SOL Configuration Parameters>
+0x2C:0x1F //<Group Extension>:<Get CPU PECI Package Config Data>
+0x2C:0x20 //<Group Extension>:<Get MDR Data Region Status>
+0x2C:0x21 //<Group Extension>:<Get MDR Region Update Complete>
+0x2C:0x22 //<Group Extension>:<Read MDR Region>
+0x2C:0x23 //<Group Extension>:<Write MDR Region>
+0x2C:0x24 //<Group Extension>:<Get MDR Region Lock>
+0x2C:0x25 //<Group Extension>:<Get System Mode>
+0x2C:0x29 //<Group Extension>:<Get TPM Configuration>
+0x2C:0x37 //<Group Extension>:<Read PCIe Cable EEPROM Data>
+0x30:0x04 //<Intel General Application>:<Get NW Switch MIB>
+0x30:0x05 //<Intel General Application>:<Get PDB FW Version>
+0x30:0x09 //<Intel General Application>:<Get BMC Config>
+0x30:0x14 //<Intel General Application>:<Get SM Signal>
+0x30:0x19 //<Intel General Application>:<Read LAN Channel Port Value>
+0x30:0x1A //<Intel General Application>:<Get NIC Info>
+0x30:0x1B //<Intel General Application>:<Get LAN Available>
+0x30:0x1D //<Intel General Application>:<Get Master MAC>
+0x30:0x1F //<Intel General Application>:<Get Secure Mode>
+0x30:0x20 //<Intel General Application>:<OEM Get SEL info>
+0x30:0x21 //<Intel General Application>:<OEM Get SEL Allocation Info>
+0x30:0x22 //<Intel General Application>:<OEM Platform Event Message>
+0x30:0x23 //<Intel General Application>:<OEM Get SEL Entry>
+0x30:0x26 //<Intel General Application>:<Set BIOS ID>
+0x30:0x27 //<Intel General Application>:<Get OEM Device Information>
+0x30:0x2E //<Intel General Application>:<Get Cold Redundancy Configuration>
+0x30:0x30 //<Intel General Application>:<Get Sensor Severity>
+0x30:0x31 //<Intel General Application>:<Get AIC Slot FRU ID SLOT POS Records>
+0x30:0x33 //<Intel General Application>:<Get Controller Status>
+0x30:0x38 //<Intel General Application>:<Get Satellite Firmware update status>
+0x30:0x39 //<Intel General Application>:<HSBP Get Owner>
+0x30:0x3C //<Intel General Application>:<Get AIC MAC>
+0x30:0x41 //<Intel General Application>:<Set System GUID>
+0x30:0x43 //<Intel General Application>:<Get BMC Reset Disables>
+0x30:0x44 //<Intel General Application>:<Send Embedded Firmware Update Status>
+0x30:0x47 //<Intel General Application>:<HSBP Get Version>
+0x30:0x55 //<Intel General Application>:<Get Power Restore Delay>
+0x30:0x58 //<Intel General Application>:<Get DIMM Fault Status>
+0x30:0x62 //<Intel General Application>:<Get Shutdown Policy>
+0x30:0x63 //<Intel General Application>:<Get Node Slot Presence>
+0x30:0x65 //<Intel General Application>:<Get HDD Drive Fault LED State>
+0x30:0x66 //<Intel General Application>:<Get Buffer Size>
+0x30:0x71 //<Intel General Application>:<Get Advanced Support>
+0x30:0x73 //<Intel General Application>:<Get EFI Payload>
+0x30:0x74 //<Intel General Application>:<Get RMM Status>
+0x30:0x75 //<Intel General Application>:<Get Voltage Name>
+0x30:0x80 //<Intel General Application>:<HSBP Get Register From Memory>
+0x30:0x81 //<Intel General Application>:<Get Power State>
+0x30:0x82 //<Intel General Application>:<Get ACPI Config>
+0x30:0x85 //<Intel General Application>:<Get SF PWM>
+0x30:0x8A //<Intel General Application>:<Get Fan Control Configuration>
+0x30:0x8B //<Intel General Application>:<Auto Fan Detect>
+0x30:0x8D //<Intel General Application>:<Get fan speed offset>
+0x30:0x8F //<Intel General Application>:<Get DIMM offset>
+0x30:0x91 //<Intel General Application>:<Get FSC Parameter>
+0x30:0x92 //<Intel General Application>:<Get Chassis Identifier>
+0x30:0x93 //<Intel General Application>:<Read Base Board Product ID>
+0x30:0x94 //<Intel General Application>:<Get BMC Revision ID>
+0x30:0x95 //<Intel General Application>:<Get Is AP CPU>
+0x30:0x9A //<Intel General Application>:<Get Processor Error Configuration and Status>
+0x30:0x9D //<Intel General Application>:<Get Fan PWM Limit>
+0x30:0xB0 //<Intel General Application>:<Get LED Status>
+0x30:0xB2 //<Intel General Application>:<Get BMC Service Status>
+0x30:0xB3 //<Intel General Application>:<Get BMC Security Control Mode>
+0x30:0xBB //<Intel General Application>:<Get CPLD Revision ID>
+0x30:0xC2 //<Intel General Application>:<Get OEM Extended Sys Info>
+0x30:0xC6 //<Intel General Application>:<Get Partition Config>
+0x30:0xC7 //<Intel General Application>:<Get Zone Information>
+0x30:0xC9 //<Intel General Application>:<Get Configuration Status>
+0x30:0xCA //<Intel General Application>:<Get Fabric Information>
+0x30:0xCB //<Intel General Application>:<Get EndPoints Information>
+0x30:0xCC //<Intel General Application>:<Get Switches Information>
+0x30:0xCD //<Intel General Application>:<Get Switch Collection Information>
+0x30:0xD0 //<Intel General Application>:<Get NVMe Drive Data>
+0x30:0xD1 //<Intel General Application>:<HSBP Statistics>
+0x30:0xD4 //<Intel General Application>:<Get BIOS Capsule (OOB Update)>
+0x30:0xE2 //<Intel General Application>:<OEM Get Reading>
+0x30:0xE5 //<Intel General Application>:<Get NMI Source>
+0x30:0xE8 //<Intel General Application>:<Get PCIe SMBus Slot Card Info>
+0x30:0xE9 //<Intel General Application>:<Get BIOS POST CODE>
+0x30:0xF9 //<Intel General Application>:<Get POST Progress Codes>
+0x30:0xFD //<Intel General Application>:<Get Riser Presence>
+0x32:0x60 //<Intel OEM Platform>:<Get PM Bus Information>
+0x32:0x63 //<Intel OEM Platform>:<Get Tach Information>
+0x32:0x8D //<Intel OEM Platform>:<Get SSD Power>
+0x3E:0x02 //<Intel Managed Data Region>:<BMC Data Region Update Event Message>
+0x3E:0x20 //<Intel Managed Data Region>:<BMC Region Status>
+0x3E:0x21 //<Intel Managed Data Region>:<BMC Region Update Complete>
+0x3E:0x22 //<Intel Managed Data Region>:<MDR Event>
+0x3E:0x23 //<Intel Managed Data Region>:<BMC Region Read>
+0x3E:0x24 //<Intel Managed Data Region>:<BMC Region Write>
+0x3E:0x25 //<Intel Managed Data Region>:<BMC Region Lock>
+0x3E:0x28 //<Intel Managed Data Region>:<Get DIMM information>
+0x3E:0x30 //<Intel Managed Data Region>:<MDR2 Status>
+0x3E:0x31 //<Intel Managed Data Region>:<MDR2 GET Direction>
+0x3E:0x32 //<Intel Managed Data Region>:<MDR2 Get Data Set Info>
+0x3E:0x33 //<Intel Managed Data Region>:<MDR2 Lock Data>
+0x3E:0x34 //<Intel Managed Data Region>:<MDR2 Unlock Data>
+0x3E:0x35 //<Intel Managed Data Region>:<MDR2 Dget Data Block>
+0x3E:0x38 //<Intel Managed Data Region>:<MDR2 Send Direction>
+0x3E:0x39 //<Intel Managed Data Region>:<MDR2 Data Info Offer>
+0x3E:0x3A //<Intel Managed Data Region>:<MDR2 Data Info>
+0x3E:0x3B //<Intel Managed Data Region>:<MDR2 Data Start>
+0x3E:0x3C //<Intel Managed Data Region>:<MDR2 Data Done>
+0x3E:0x3D //<Intel Managed Data Region>:<MDR2 Data Block>
+0x3E:0x41 //<Intel Managed Data Region>:<Enter Platform Debug Log file transfer mode>
+0x3E:0x42 //<Intel Managed Data Region>:<Read Platform Debug Log file>
+0x3E:0x43 //<Intel Managed Data Region>:<Status of the Platform Debug Log file transfer mode>
+0x3E:0x44 //<Intel Managed Data Region>:<Exit Platform Debug Log file transfer mode>
+0x3E:0x50 //<Intel Managed Data Region>:<Node IPMB slave address>
+0x3E:0x51 //<Intel Managed Data Region>:<Slot IPMB>
+0x3E:0x52 //<Intel Managed Data Region>:<Slot I2C Master Write Read>
+0x3E:0x75 //<Intel Managed Data Region>:<Get Remote Log IP>
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/phosphor-ipmi-host.service b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/phosphor-ipmi-host.service
new file mode 100644
index 000000000..b09bbf890
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/phosphor-ipmi-host.service
@@ -0,0 +1,28 @@
+[Unit]
+Description=Phosphor Inband IPMI
+# TODO openbmc/openbmc#2059 - The wants/after below should be based on providers
+Wants=mapper-wait@-xyz-openbmc_project-control-host0-boot.service
+After=mapper-wait@-xyz-openbmc_project-control-host0-boot.service
+Wants=mapper-wait@-xyz-openbmc_project-control-host0-boot-one_time.service
+After=mapper-wait@-xyz-openbmc_project-control-host0-boot-one_time.service
+Wants=mapper-wait@-xyz-openbmc_project-control-host0-power_restore_policy.service
+After=mapper-wait@-xyz-openbmc_project-control-host0-power_restore_policy.service
+Wants=mapper-wait@-xyz-openbmc_project-control-security-restriction_mode.service
+After=mapper-wait@-xyz-openbmc_project-control-security-restriction_mode.service
+Wants=mapper-wait@-xyz-openbmc_project-state-os.service
+After=mapper-wait@-xyz-openbmc_project-state-os.service
+Wants=clear-once.service
+After=clear-once.service
+
+[Service]
+Restart=always
+RestartSec=5
+StartLimitBurst=10
+ExecStart=/usr/bin/env ipmid
+SyslogIdentifier=ipmid
+RuntimeDirectory = ipmi
+RuntimeDirectoryPreserve = yes
+StateDirectory = ipmi
+
+[Install]
+WantedBy={SYSTEMD_DEFAULT_TARGET}
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host_%.bbappend b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host_%.bbappend
new file mode 100644
index 000000000..a50d5fd7f
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host_%.bbappend
@@ -0,0 +1,45 @@
+FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
+
+#todo yong unpin this
+SRC_URI = "git://github.com/openbmc/phosphor-host-ipmid;nobranch=1"
+SRCREV = "c514d874e4ce3ed1f747cfcb4bab5990393c55e8"
+
+SRC_URI += "file://phosphor-ipmi-host.service \
+ file://host-ipmid-whitelist.conf \
+ file://0010-fix-get-system-GUID-ipmi-command.patch \
+ file://0013-ipmi-add-set-bios-id-to-whitelist.patch \
+ file://0039-ipmi-add-oem-command-get-AIC-FRU-to-whitelist.patch \
+ file://0050-enable-6-oem-commands.patch \
+ file://0053-Fix-keep-looping-issue-when-entering-OS.patch \
+ file://0056-add-SetInProgress-to-get-set-boot-option-cmd.patch \
+ file://0057-Add-timer-use-actions-support.patch \
+ file://0059-Move-Set-SOL-config-parameter-to-host-ipmid.patch \
+ file://0060-Move-Get-SOL-config-parameter-to-host-ipmid.patch \
+ file://0062-Update-IPMI-Chassis-Control-command.patch \
+ file://0063-Save-the-pre-timeout-interrupt-in-dbus-property.patch \
+ file://0064-Enable-watchdog-to-save-useflag-after-host-power-off.patch \
+ file://0064-Update-provisioning-mode-filter-logic.patch \
+ "
+
+EXTRA_OECONF_append = " --disable-i2c-whitelist-check"
+
+RDEPENDS_${PN}_remove = "clear-once"
+
+# remove the softpoweroff service since we do not need it
+SYSTEMD_SERVICE_${PN}_remove += " \
+ xyz.openbmc_project.Ipmi.Internal.SoftPowerOff.service"
+
+SYSTEMD_LINK_${PN}_remove += " \
+ ../xyz.openbmc_project.Ipmi.Internal.SoftPowerOff.service:obmc-host-shutdown@0.target.requires/xyz.openbmc_project.Ipmi.Internal.SoftPowerOff.service \
+ "
+FILES_${PN}_remove = " \
+ ${systemd_unitdir}/system/obmc-host-shutdown@0.target.requires/ \
+ ${systemd_unitdir}/system/obmc-host-shutdown@0.target.requires/xyz.openbmc_project.Ipmi.Internal.SoftPowerOff.service \
+ "
+do_configure_append(){
+ cp -f ${WORKDIR}/host-ipmid-whitelist.conf ${S}
+}
+
+do_install_append(){
+ rm -f ${D}/${bindir}/phosphor-softpoweroff
+}
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-ipmb_%.bbappend b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-ipmb_%.bbappend
new file mode 100644
index 000000000..f33be5760
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-ipmb_%.bbappend
@@ -0,0 +1,2 @@
+SRC_URI = "git://github.com/openbmc/ipmbbridge.git"
+SRCREV = "bbfd00abdbc6d2f7c0389eae91cc055a1d4fe0c3"
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-kcs/99-ipmi-kcs.rules b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-kcs/99-ipmi-kcs.rules
new file mode 100644
index 000000000..0a64b58db
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-kcs/99-ipmi-kcs.rules
@@ -0,0 +1,2 @@
+KERNEL=="ipmi-kcs3", SYMLINK+="ipmi_kcs3"
+KERNEL=="ipmi-kcs4", SYMLINK+="ipmi_kcs4"
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-kcs_%.bbappend b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-kcs_%.bbappend
new file mode 100644
index 000000000..140d1b302
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-kcs_%.bbappend
@@ -0,0 +1,21 @@
+FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
+
+#SYSTEMD_SUBSTITUTIONS_remove = "KCS_DEVICE:${KCS_DEVICE}:${DBUS_SERVICE_${PN}}"
+
+# Default kcs device is ipmi-kcs3; this is SMS.
+# Add SMM kcs device instance
+
+# Replace the '-' to '_', since Dbus object/interface names do not allow '-'.
+KCS_DEVICE = "ipmi_kcs3"
+SMM_DEVICE = "ipmi_kcs4"
+SYSTEMD_SERVICE_${PN}_append = " ${PN}@${SMM_DEVICE}.service "
+
+SRC_URI = "git://github.com/openbmc/kcsbridge.git"
+SRCREV = "2cdc49585235a6557c9cbb6c8b75c064fc02681a"
+
+SRC_URI += "file://99-ipmi-kcs.rules"
+
+do_install_append() {
+ install -d ${D}${base_libdir}/udev/rules.d
+ install -m 0644 ${WORKDIR}/99-ipmi-kcs.rules ${D}${base_libdir}/udev/rules.d/
+}
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-net/00010-Change-Authentication-Parameter.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-net/00010-Change-Authentication-Parameter.patch
new file mode 100644
index 000000000..867b3aba6
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-net/00010-Change-Authentication-Parameter.patch
@@ -0,0 +1,40 @@
+From 0fd38eb0a155cb11ff5a5452087f68c46d12111b Mon Sep 17 00:00:00 2001
+From: Cheng C Yang <cheng.c.yang@intel.com>
+Date: Thu, 28 Mar 2019 18:10:40 +0800
+Subject: [PATCH] Change Authentication Parameter
+
+Seprate D-bus interface Authentication to forceAuthentication,
+forceEncryption, Privilege according to the related change in
+sol-dbus-interface.
+
+Tested By:
+ipmitool -I lanplus -H x -U x -P x raw 0x0c 0x21 0x0e 0x02 0x03
+ipmitool -I lanplus -H x -U x -P x raw 0x0c 0x21 0x0e 0x02 0xc2
+The parameters has been changed to the request data in above command.
+
+Signed-off-by: Cheng C Yang <cheng.c.yang@intel.com>
+---
+ sol/sol_manager.cpp | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/sol/sol_manager.cpp b/sol/sol_manager.cpp
+index de36723..0bd837e 100644
+--- a/sol/sol_manager.cpp
++++ b/sol/sol_manager.cpp
+@@ -195,8 +195,12 @@ void Manager::updateSOLParameter()
+
+ enable = std::get<bool>(properties["Enable"]);
+
++ forceEncrypt = std::get<bool>(properties["ForceEncryption"]);
++
++ forceAuth = std::get<bool>(properties["ForceAuthentication"]);
++
+ solMinPrivilege = static_cast<session::Privilege>(
+- std::get<uint8_t>(properties["Authentication"]));
++ std::get<uint8_t>(properties["Privilege"]));
+
+ accumulateInterval =
+ std::get<uint8_t>((properties["AccumulateIntervalMS"])) *
+--
+2.16.2
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-net/0006-Modify-dbus-namespace-of-chassis-control-for-guid.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-net/0006-Modify-dbus-namespace-of-chassis-control-for-guid.patch
new file mode 100644
index 000000000..0ad625a1f
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-net/0006-Modify-dbus-namespace-of-chassis-control-for-guid.patch
@@ -0,0 +1,39 @@
+From 6fc55bb689272d34ff6616cdd4b24367ea39c749 Mon Sep 17 00:00:00 2001
+From: Kuiying Wang <kuiying.wang@intel.com>
+Date: Mon, 2 Jul 2018 15:51:52 +0800
+Subject: [PATCH] Modify dbus namespace of chassis control for guid.cpp
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Switch chassis control service namespace for guid.cpp from “org” to “xyz”,
+to compatible with new intel-chassis services
+
+Signed-off-by: Kuiying Wang <kuiying.wang@intel.com>
+---
+ command/guid.cpp | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+Index: phosphor-net-ipmid.clean/command/guid.cpp
+===================================================================
+--- phosphor-net-ipmid.clean.orig/command/guid.cpp
++++ phosphor-net-ipmid.clean/command/guid.cpp
+@@ -21,7 +21,8 @@ namespace command
+
+ std::unique_ptr<sdbusplus::bus::match_t> matchPtr(nullptr);
+
+-static constexpr auto guidObjPath = "/org/openbmc/control/chassis0";
++static constexpr auto guidObjPath =
++ "/xyz/openbmc_project/Chassis/Control/Chassis0";
+ static constexpr auto propInterface = "org.freedesktop.DBus.Properties";
+
+ Guid getSystemGUID()
+@@ -31,7 +32,7 @@ Guid getSystemGUID()
+ Guid guid = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+ 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10};
+
+- constexpr auto chassisIntf = "org.openbmc.control.Chassis";
++ constexpr auto chassisIntf = "xyz.openbmc_project.Chassis.Control.Chassis";
+
+ sd_bus_message* reply = nullptr;
+ sd_bus_error error = SD_BUS_ERROR_NULL;
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-net/0009-Add-dbus-interface-for-sol-commands.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-net/0009-Add-dbus-interface-for-sol-commands.patch
new file mode 100644
index 000000000..dc7f7357c
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-net/0009-Add-dbus-interface-for-sol-commands.patch
@@ -0,0 +1,319 @@
+From 97c21a556702a0d65096b30c07ef23f15cb6a7d9 Mon Sep 17 00:00:00 2001
+From: Cheng C Yang <cheng.c.yang@intel.com>
+Date: Wed, 3 Jul 2019 07:39:47 +0800
+Subject: [PATCH] Add dbus interface for sol commands
+
+Add dbus interface for sol config parameters so that after move set/get
+sol config parameter command from net-ipmid to host-ipmid, the command
+can send config parameters to net-ipmid sol service through the dbus
+interface.
+
+Tested by:
+busctl introspect xyz.openbmc_project.Settings /xyz/openbmc_project
+/network/host0/sol can show correct dbus properties of sol parameters.
+ipmitool -I lanplus -H x -U x -P x raw 0x0c 0x21 0x0e 0x00 0x01
+ipmitool -I lanplus -H x -U x -P x raw 0x0c 0x21 0x0e 0x01 0x00
+ipmitool -I lanplus -H x -U x -P x raw 0x0c 0x21 0x0e 0x02 0x83
+ipmitool -I lanplus -H x -U x -P x raw 0x0c 0x21 0x0e 0x03 0x5 0x03
+ipmitool -I lanplus -H x -U x -P x raw 0x0c 0x21 0x0e 0x04 0x5 0x03
+all these commands can change the dbus properties as the value in
+above commands.
+Before and after run these commands, ipmitool -I lanplus -H x -U x
+-P x sol activate can start sol session correctly.
+After reboot BMC, "Progress" property in dbus interface change back
+to 0 and other properties will not reset to default value.
+
+Signed-off-by: Cheng C Yang <cheng.c.yang@intel.com>
+---
+ command/payload_cmds.cpp | 3 ++
+ command/sol_cmds.cpp | 84 -------------------------------
+ sol/sol_manager.cpp | 125 +++++++++++++++++++++++++++++++++++++++++++++++
+ sol/sol_manager.hpp | 1 +
+ sol_module.cpp | 6 ---
+ 5 files changed, 129 insertions(+), 90 deletions(-)
+
+diff --git a/command/payload_cmds.cpp b/command/payload_cmds.cpp
+index c32a510..17167a7 100644
+--- a/command/payload_cmds.cpp
++++ b/command/payload_cmds.cpp
+@@ -34,6 +34,9 @@ std::vector<uint8_t> activatePayload(const std::vector<uint8_t>& inPayload,
+ return outPayload;
+ }
+
++ std::get<sol::Manager&>(singletonPool)
++ .updateSOLParameter(ipmi::convertCurrentChannelNum(
++ ipmi::currentChNum, getInterfaceIndex()));
+ if (!std::get<sol::Manager&>(singletonPool).enable)
+ {
+ response->completionCode = IPMI_CC_PAYLOAD_TYPE_DISABLED;
+diff --git a/command/sol_cmds.cpp b/command/sol_cmds.cpp
+index a8fa410..804b5ea 100644
+--- a/command/sol_cmds.cpp
++++ b/command/sol_cmds.cpp
+@@ -65,90 +65,6 @@ void activating(uint8_t payloadInstance, uint32_t sessionID)
+ outPayload);
+ }
+
+-std::vector<uint8_t> setConfParams(const std::vector<uint8_t>& inPayload,
+- const message::Handler& handler)
+-{
+- std::vector<uint8_t> outPayload(sizeof(SetConfParamsResponse));
+- auto request =
+- reinterpret_cast<const SetConfParamsRequest*>(inPayload.data());
+- auto response = reinterpret_cast<SetConfParamsResponse*>(outPayload.data());
+- response->completionCode = IPMI_CC_OK;
+-
+- switch (static_cast<Parameter>(request->paramSelector))
+- {
+- case Parameter::PROGRESS:
+- {
+- uint8_t progress = request->value & progressMask;
+- std::get<sol::Manager&>(singletonPool).progress = progress;
+- break;
+- }
+- case Parameter::ENABLE:
+- {
+- bool enable = request->value & enableMask;
+- std::get<sol::Manager&>(singletonPool).enable = enable;
+- break;
+- }
+- case Parameter::AUTHENTICATION:
+- {
+- if (!request->auth.auth || !request->auth.encrypt)
+- {
+- response->completionCode = ipmiCCWriteReadParameter;
+- }
+- else if (request->auth.privilege <
+- static_cast<uint8_t>(session::Privilege::USER) ||
+- request->auth.privilege >
+- static_cast<uint8_t>(session::Privilege::OEM))
+- {
+- response->completionCode = IPMI_CC_INVALID_FIELD_REQUEST;
+- }
+- else
+- {
+- std::get<sol::Manager&>(singletonPool).solMinPrivilege =
+- static_cast<session::Privilege>(request->auth.privilege);
+- }
+- break;
+- }
+- case Parameter::ACCUMULATE:
+- {
+- using namespace std::chrono_literals;
+-
+- if (request->acc.threshold == 0)
+- {
+- response->completionCode = IPMI_CC_INVALID_FIELD_REQUEST;
+- break;
+- }
+-
+- std::get<sol::Manager&>(singletonPool).accumulateInterval =
+- request->acc.interval * sol::accIntervalFactor * 1ms;
+- std::get<sol::Manager&>(singletonPool).sendThreshold =
+- request->acc.threshold;
+- break;
+- }
+- case Parameter::RETRY:
+- {
+- using namespace std::chrono_literals;
+-
+- std::get<sol::Manager&>(singletonPool).retryCount =
+- request->retry.count;
+- std::get<sol::Manager&>(singletonPool).retryInterval =
+- request->retry.interval * sol::retryIntervalFactor * 1ms;
+- break;
+- }
+- case Parameter::PORT:
+- {
+- response->completionCode = ipmiCCWriteReadParameter;
+- break;
+- }
+- case Parameter::NVBITRATE:
+- case Parameter::VBITRATE:
+- case Parameter::CHANNEL:
+- default:
+- response->completionCode = ipmiCCParamNotSupported;
+- }
+-
+- return outPayload;
+-}
+-
+ std::vector<uint8_t> getConfParams(const std::vector<uint8_t>& inPayload,
+ const message::Handler& handler)
+ {
+diff --git a/sol/sol_manager.cpp b/sol/sol_manager.cpp
+index 2046fe4..eedd28a 100644
+--- a/sol/sol_manager.cpp
++++ b/sol/sol_manager.cpp
+@@ -12,7 +12,13 @@
+ #include <boost/asio/write.hpp>
+ #include <chrono>
+ #include <cmath>
++#include <ipmid/utils.hpp>
+ #include <phosphor-logging/log.hpp>
++#include <sdbusplus/message/types.hpp>
++
++constexpr const char* solInterface = "xyz.openbmc_project.Ipmi.SOL";
++constexpr const char* solPath = "/xyz/openbmc_project/ipmi/sol/";
++constexpr const char* PROP_INTF = "org.freedesktop.DBus.Properties";
+
+ namespace sol
+ {
+@@ -93,6 +99,125 @@ void Manager::stopHostConsole()
+ }
+ }
+
++std::string getService(sdbusplus::bus::bus& bus, const std::string& intf,
++ const std::string& path)
++{
++ auto mapperCall =
++ bus.new_method_call("xyz.openbmc_project.ObjectMapper",
++ "/xyz/openbmc_project/object_mapper",
++ "xyz.openbmc_project.ObjectMapper", "GetObject");
++
++ mapperCall.append(path);
++ mapperCall.append(std::vector<std::string>({intf}));
++
++ std::map<std::string, std::vector<std::string>> mapperResponse;
++
++ try
++ {
++ auto mapperResponseMsg = bus.call(mapperCall);
++ mapperResponseMsg.read(mapperResponse);
++ }
++ catch (sdbusplus::exception_t&)
++ {
++ throw std::runtime_error("ERROR in mapper call");
++ }
++
++ if (mapperResponse.begin() == mapperResponse.end())
++ {
++ throw std::runtime_error("ERROR in reading the mapper response");
++ }
++
++ return mapperResponse.begin()->first;
++}
++
++ipmi::PropertyMap getAllDbusProperties(sdbusplus::bus::bus& bus,
++ const std::string& service,
++ const std::string& objPath,
++ const std::string& interface)
++{
++ ipmi::PropertyMap properties;
++
++ sdbusplus::message::message method = bus.new_method_call(
++ service.c_str(), objPath.c_str(), PROP_INTF, "GetAll");
++
++ method.append(interface);
++
++ try
++ {
++ sdbusplus::message::message reply = bus.call(method);
++ reply.read(properties);
++ }
++ catch (sdbusplus::exception_t&)
++ {
++ phosphor::logging::log<phosphor::logging::level::ERR>(
++ "Failed to get all properties",
++ phosphor::logging::entry("PATH=%s", objPath.c_str()),
++ phosphor::logging::entry("INTERFACE=%s", interface.c_str()));
++ throw std::runtime_error("ERROR in reading proerties");
++ }
++
++ return properties;
++}
++
++void Manager::updateSOLParameter(uint8_t channelNum)
++{
++ std::variant<uint8_t, bool> value;
++ sdbusplus::bus::bus dbus(ipmid_get_sd_bus_connection());
++ static std::string solService{};
++ ipmi::PropertyMap properties;
++ std::string ethdevice = ipmi::getChannelName(channelNum);
++ std::string solPathWitheEthName = solPath + ethdevice;
++ if (solService.empty())
++ {
++ try
++ {
++ solService = getService(dbus, solInterface, solPathWitheEthName);
++ }
++ catch (const std::runtime_error& e)
++ {
++ solService.clear();
++ phosphor::logging::log<phosphor::logging::level::ERR>(
++ "Error: get SOL service failed");
++ return;
++ }
++ }
++ try
++ {
++ properties = getAllDbusProperties(dbus, solService, solPathWitheEthName,
++ solInterface);
++ }
++ catch (const std::runtime_error&)
++ {
++ phosphor::logging::log<phosphor::logging::level::ERR>(
++ "Error setting sol parameter");
++ return;
++ }
++
++ progress = std::get<uint8_t>(properties["Progress"]);
++
++ enable = std::get<bool>(properties["Enable"]);
++
++ forceEncrypt = std::get<bool>(properties["ForceEncryption"]);
++
++ forceAuth = std::get<bool>(properties["ForceAuthentication"]);
++
++ solMinPrivilege = static_cast<session::Privilege>(
++ std::get<uint8_t>(properties["Privilege"]));
++
++ accumulateInterval =
++ std::get<uint8_t>((properties["AccumulateIntervalMS"])) *
++ sol::accIntervalFactor * 1ms;
++
++ sendThreshold = std::get<uint8_t>(properties["Threshold"]);
++
++ retryCount = std::get<uint8_t>(properties["RetryCount"]);
++
++ retryInterval = std::get<uint8_t>(properties["RetryIntervalMS"]) *
++ sol::retryIntervalFactor * 1ms;
++
++ return;
++}
++
+ void Manager::startPayloadInstance(uint8_t payloadInstance,
+ session::SessionID sessionID)
+ {
+diff --git a/sol/sol_manager.hpp b/sol/sol_manager.hpp
+index 5d96890..00da9fb 100644
+--- a/sol/sol_manager.hpp
++++ b/sol/sol_manager.hpp
+@@ -248,6 +248,7 @@ class Manager
+ * @return 0 on success and errno on failure.
+ */
+ int writeConsoleSocket(const std::vector<uint8_t>& input) const;
++ void updateSOLParameter(uint8_t channelNum);
+
+ private:
+ SOLPayloadMap payloadMap;
+diff --git a/sol_module.cpp b/sol_module.cpp
+index 8200e74..2b1fb46 100644
+--- a/sol_module.cpp
++++ b/sol_module.cpp
+@@ -42,12 +42,6 @@ void registerCommands()
+ &getPayloadInfo,
+ session::Privilege::USER,
+ false},
+- // Set SOL Configuration Parameters
+- {{(static_cast<uint32_t>(message::PayloadType::IPMI) << 16) |
+- static_cast<uint16_t>(::command::NetFns::TRANSPORT) | 0x21},
+- &setConfParams,
+- session::Privilege::ADMIN,
+- false},
+ // Get SOL Configuration Parameters
+ {{(static_cast<uint32_t>(message::PayloadType::IPMI) << 16) |
+ static_cast<uint16_t>(::command::NetFns::TRANSPORT) | 0x22},
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-net/0011-Remove-Get-SOL-Config-Command-from-Netipmid.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-net/0011-Remove-Get-SOL-Config-Command-from-Netipmid.patch
new file mode 100644
index 000000000..da173704b
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-net/0011-Remove-Get-SOL-Config-Command-from-Netipmid.patch
@@ -0,0 +1,336 @@
+From a36f181163974b2da0a954fc97a89fb2cdbd7287 Mon Sep 17 00:00:00 2001
+From: Cheng C Yang <cheng.c.yang@intel.com>
+Date: Tue, 30 Apr 2019 05:35:31 +0800
+Subject: [PATCH] Remove Get SOL Config Command from Netipmid
+
+Since Get SOL Config Parameter command already exists in host-ipmid, and
+can be shared to net channel, remove this command from net-ipmid.
+
+Tested:
+Run ipmitool -I lanplus -H xxx -U root -P 0penBmc sol info, the command
+returns the same result as ipmitool sol info as below.
+Info: SOL parameter 'Nonvolatile Bitrate (5)' not supported
+Info: SOL parameter 'Volatile Bitrate (6)' not supported
+Info: SOL parameter 'Payload Channel (7)' not supported - defaulting to 0x0e
+Set in progress : set-complete
+Enabled : true
+Force Encryption : true
+Force Authentication : true
+Privilege Level : USER
+Character Accumulate Level (ms) : 100
+Character Send Threshold : 1
+Retry Count : 3
+Retry Interval (ms) : 100
+Volatile Bit Rate (kbps) : IPMI-Over-Serial-Setting
+Non-Volatile Bit Rate (kbps) : IPMI-Over-Serial-Setting
+Payload Channel : 14 (0x0e)
+Payload Port : 623
+
+Signed-off-by: Cheng C Yang <cheng.c.yang@intel.com>
+---
+ command/sol_cmds.cpp | 91 ----------------------------
+ command/sol_cmds.hpp | 168 ---------------------------------------------------
+ sol_module.cpp | 6 --
+ 3 files changed, 265 deletions(-)
+
+diff --git a/command/sol_cmds.cpp b/command/sol_cmds.cpp
+index 804b5ea..8b2d041 100644
+--- a/command/sol_cmds.cpp
++++ b/command/sol_cmds.cpp
+@@ -65,97 +65,6 @@ void activating(uint8_t payloadInstance, uint32_t sessionID)
+ outPayload);
+ }
+
+-std::vector<uint8_t> getConfParams(const std::vector<uint8_t>& inPayload,
+- const message::Handler& handler)
+-{
+- std::vector<uint8_t> outPayload(sizeof(GetConfParamsResponse));
+- auto request =
+- reinterpret_cast<const GetConfParamsRequest*>(inPayload.data());
+- auto response = reinterpret_cast<GetConfParamsResponse*>(outPayload.data());
+- response->completionCode = IPMI_CC_OK;
+- response->paramRev = parameterRevision;
+-
+- if (request->getParamRev)
+- {
+- return outPayload;
+- }
+-
+- switch (static_cast<Parameter>(request->paramSelector))
+- {
+- case Parameter::PROGRESS:
+- {
+- outPayload.push_back(
+- std::get<sol::Manager&>(singletonPool).progress);
+- break;
+- }
+- case Parameter::ENABLE:
+- {
+- outPayload.push_back(std::get<sol::Manager&>(singletonPool).enable);
+- break;
+- }
+- case Parameter::AUTHENTICATION:
+- {
+- Auth value{0};
+-
+- value.encrypt = std::get<sol::Manager&>(singletonPool).forceEncrypt;
+- value.auth = std::get<sol::Manager&>(singletonPool).forceAuth;
+- value.privilege = static_cast<uint8_t>(
+- std::get<sol::Manager&>(singletonPool).solMinPrivilege);
+- auto buffer = reinterpret_cast<const uint8_t*>(&value);
+-
+- std::copy_n(buffer, sizeof(value), std::back_inserter(outPayload));
+- break;
+- }
+- case Parameter::ACCUMULATE:
+- {
+- Accumulate value{0};
+-
+- value.interval = std::get<sol::Manager&>(singletonPool)
+- .accumulateInterval.count() /
+- sol::accIntervalFactor;
+- value.threshold =
+- std::get<sol::Manager&>(singletonPool).sendThreshold;
+- auto buffer = reinterpret_cast<const uint8_t*>(&value);
+-
+- std::copy_n(buffer, sizeof(value), std::back_inserter(outPayload));
+- break;
+- }
+- case Parameter::RETRY:
+- {
+- Retry value{0};
+-
+- value.count = std::get<sol::Manager&>(singletonPool).retryCount;
+- value.interval =
+- std::get<sol::Manager&>(singletonPool).retryInterval.count() /
+- sol::retryIntervalFactor;
+- auto buffer = reinterpret_cast<const uint8_t*>(&value);
+-
+- std::copy_n(buffer, sizeof(value), std::back_inserter(outPayload));
+- break;
+- }
+- case Parameter::PORT:
+- {
+- auto port = endian::to_ipmi<uint16_t>(IPMI_STD_PORT);
+- auto buffer = reinterpret_cast<const uint8_t*>(&port);
+-
+- std::copy_n(buffer, sizeof(port), std::back_inserter(outPayload));
+- break;
+- }
+- case Parameter::CHANNEL:
+- {
+- outPayload.push_back(
+- std::get<sol::Manager&>(singletonPool).channel);
+- break;
+- }
+- case Parameter::NVBITRATE:
+- case Parameter::VBITRATE:
+- default:
+- response->completionCode = ipmiCCParamNotSupported;
+- }
+-
+- return outPayload;
+-}
+-
+ } // namespace command
+
+ } // namespace sol
+diff --git a/command/sol_cmds.hpp b/command/sol_cmds.hpp
+index 182b73e..10cbf25 100644
+--- a/command/sol_cmds.hpp
++++ b/command/sol_cmds.hpp
+@@ -62,174 +62,6 @@ struct ActivatingRequest
+ */
+ void activating(uint8_t payloadInstance, uint32_t sessionID);
+
+-/** @enum Parameter
+- *
+- * SOL parameters are volatile, they are initialized by the SOL manager.
+- * They can be read using Get SOL configuration parameters command and updated
+- * using Set SOL configuration parameters command.
+- */
+-enum class Parameter
+-{
+- PROGRESS, //!< Set In Progress.
+- ENABLE, //!< SOL Enable.
+- AUTHENTICATION, //!< SOL Authentication.
+- ACCUMULATE, //!< Character Accumulate Interval & Send Threshold.
+- RETRY, //!< SOL Retry.
+- NVBITRATE, //!< SOL non-volatile bit rate.
+- VBITRATE, //!< SOL volatile bit rate.
+- CHANNEL, //!< SOL payload channel.
+- PORT, //!< SOL payload port.
+-};
+-
+-constexpr uint8_t progressMask = 0x03;
+-constexpr uint8_t enableMask = 0x01;
+-
+-/** @struct Auth
+- *
+- * SOL authentication parameter.
+- */
+-struct Auth
+-{
+-#if BYTE_ORDER == LITTLE_ENDIAN
+- uint8_t privilege : 4; //!< SOL privilege level.
+- uint8_t reserved : 2; //!< Reserved.
+- uint8_t auth : 1; //!< Force SOL payload Authentication.
+- uint8_t encrypt : 1; //!< Force SOL payload encryption.
+-#endif
+-
+-#if BYTE_ORDER == BIG_ENDIAN
+- uint8_t encrypt : 1; //!< Force SOL payload encryption.
+- uint8_t auth : 1; //!< Force SOL payload Authentication.
+- uint8_t reserved : 2; //!< Reserved.
+- uint8_t privilege : 4; //!< SOL privilege level.
+-#endif
+-} __attribute__((packed));
+-
+-/** @struct Accumulate
+- *
+- * Character accumulate interval & Character send threshold.
+- */
+-struct Accumulate
+-{
+- uint8_t interval; //!< Character accumulate interval.
+- uint8_t threshold; //!< Character send threshold.
+-} __attribute__((packed));
+-
+-constexpr uint8_t retryCountMask = 0x07;
+-
+-/** @struct Retry
+- *
+- * SOL retry count and interval.
+- */
+-struct Retry
+-{
+-#if BYTE_ORDER == LITTLE_ENDIAN
+- uint8_t count : 3; //!< SOL retry count.
+- uint8_t reserved : 5; //!< Reserved.
+-#endif
+-
+-#if BYTE_ORDER == BIG_ENDIAN
+- uint8_t reserved : 5; //!< Reserved.
+- uint8_t count : 3; //!< SOL retry count.
+-#endif
+-
+- uint8_t interval; //!< SOL retry interval.
+-} __attribute__((packed));
+-
+-constexpr uint8_t ipmiCCParamNotSupported = 0x80;
+-constexpr uint8_t ipmiCCInvalidSetInProgress = 0x81;
+-constexpr uint8_t ipmiCCWriteReadParameter = 0x82;
+-constexpr uint8_t ipmiCCReadWriteParameter = 0x83;
+-constexpr uint8_t parameterRevision = 0x11;
+-
+-/** @struct SetConfParamsRequest
+- *
+- * IPMI payload for Set SOL configuration parameters command request.
+- */
+-struct SetConfParamsRequest
+-{
+-#if BYTE_ORDER == LITTLE_ENDIAN
+- uint8_t channelNumber : 4; //!< Channel number.
+- uint8_t reserved : 4; //!< Reserved.
+-#endif
+-
+-#if BYTE_ORDER == BIG_ENDIAN
+- uint8_t reserved : 4; //!< Reserved.
+- uint8_t channelNumber : 4; //!< Channel number.
+-#endif
+-
+- uint8_t paramSelector; //!< Parameter selector.
+- union
+- {
+- uint8_t value; //!< Represents one byte SOL parameters.
+- struct Accumulate acc; //!< Character accumulate values.
+- struct Retry retry; //!< Retry values.
+- struct Auth auth; //!< Authentication parameters.
+- };
+-} __attribute__((packed));
+-
+-/** @struct SetConfParamsResponse
+- *
+- * IPMI payload for Set SOL configuration parameters command response.
+- */
+-struct SetConfParamsResponse
+-{
+- uint8_t completionCode; //!< Completion code.
+-} __attribute__((packed));
+-
+-/** @brief Set SOL configuration parameters command.
+- *
+- * @param[in] inPayload - Request data for the command.
+- * @param[in] handler - Reference to the message handler.
+- *
+- * @return Response data for the command.
+- */
+-std::vector<uint8_t> setConfParams(const std::vector<uint8_t>& inPayload,
+- const message::Handler& handler);
+-
+-/** @struct GetConfParamsRequest
+- *
+- * IPMI payload for Get SOL configuration parameters command request.
+- */
+-struct GetConfParamsRequest
+-{
+-#if BYTE_ORDER == LITTLE_ENDIAN
+- uint8_t channelNum : 4; //!< Channel number.
+- uint8_t reserved : 3; //!< Reserved.
+- uint8_t getParamRev : 1; //!< Get parameter or Get parameter revision
+-#endif
+-
+-#if BYTE_ORDER == BIG_ENDIAN
+- uint8_t getParamRev : 1; //!< Get parameter or Get parameter revision
+- uint8_t reserved : 3; //!< Reserved.
+- uint8_t channelNum : 4; //!< Channel number.
+-#endif
+-
+- uint8_t paramSelector; //!< Parameter selector.
+- uint8_t setSelector; //!< Set selector.
+- uint8_t blockSelector; //!< Block selector.
+-} __attribute__((packed));
+-
+-/** @struct GetConfParamsResponse
+- *
+- * IPMI payload for Get SOL configuration parameters command response.
+- */
+-struct GetConfParamsResponse
+-{
+- uint8_t completionCode; //!< Completion code.
+- uint8_t paramRev; //!< Parameter revision.
+-} __attribute__((packed));
+-
+-/** @brief Get SOL configuration parameters command.
+- *
+- * @param[in] inPayload - Request data for the command.
+- * @param[in] handler - Reference to the message handler.
+- *
+- * @return Response data for the command.
+- */
+-std::vector<uint8_t> getConfParams(const std::vector<uint8_t>& inPayload,
+- const message::Handler& handler);
+-
+ } // namespace command
+
+ } // namespace sol
+diff --git a/sol_module.cpp b/sol_module.cpp
+index 2b1fb46..6da82c0 100644
+--- a/sol_module.cpp
++++ b/sol_module.cpp
+@@ -42,12 +42,6 @@ void registerCommands()
+ &getPayloadInfo,
+ session::Privilege::USER,
+ false},
+- // Get SOL Configuration Parameters
+- {{(static_cast<uint32_t>(message::PayloadType::IPMI) << 16) |
+- static_cast<uint16_t>(::command::NetFns::TRANSPORT) | 0x22},
+- &getConfParams,
+- session::Privilege::USER,
+- false},
+ };
+
+ for (const auto& iter : commands)
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-net_%.bbappend b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-net_%.bbappend
new file mode 100644
index 000000000..7f7d89105
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-net_%.bbappend
@@ -0,0 +1,26 @@
+inherit useradd
+
+# TODO: This should be removed, once up-stream bump up
+# issue is resolved
+SRC_URI += "git://github.com/openbmc/phosphor-net-ipmid"
+SRCREV = "dafe36444fa438030fdf27089b0e94d8d88411dc"
+
+USERADD_PACKAGES = "${PN}"
+# add a group called ipmi
+GROUPADD_PARAM_${PN} = "ipmi "
+
+# Default rmcpp iface is eth0; channel 1
+# Add channel 2 instance (eth1)
+RMCPP_EXTRA = "eth1"
+SYSTEMD_SERVICE_${PN} += " \
+ ${PN}@${RMCPP_EXTRA}.service \
+ ${PN}@${RMCPP_EXTRA}.socket \
+ "
+
+FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
+
+SRC_URI += " file://0006-Modify-dbus-namespace-of-chassis-control-for-guid.patch \
+ file://0009-Add-dbus-interface-for-sol-commands.patch \
+ file://0011-Remove-Get-SOL-Config-Command-from-Netipmid.patch \
+ "
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-sensor-inventory%.bbappend b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-sensor-inventory%.bbappend
new file mode 100644
index 000000000..72d991c7e
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-sensor-inventory%.bbappend
@@ -0,0 +1 @@
+FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-sensor-inventory%/config.yaml b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-sensor-inventory%/config.yaml
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-sensor-inventory%/config.yaml
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-node-manager-proxy_git.bb b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-node-manager-proxy_git.bb
new file mode 100644
index 000000000..fd0a6562b
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-node-manager-proxy_git.bb
@@ -0,0 +1,19 @@
+SUMMARY = "Node Manager Proxy"
+DESCRIPTION = "The Node Manager Proxy provides a simple interface for communicating \
+with Management Engine via IPMB"
+
+SRC_URI = "git://git@github.com/Intel-BMC/node-manager;protocol=ssh"
+SRCREV = "cceeff9cd35aa548cba039b8ad47c20c5870fa27"
+PV = "0.1+git${SRCPV}"
+
+LICENSE = "Apache-2.0"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=e3fc50a88d0a364313df4b21ef20c29e"
+
+SYSTEMD_SERVICE_${PN} = "node-manager-proxy.service"
+
+DEPENDS = "sdbusplus \
+ phosphor-logging \
+ boost"
+
+S = "${WORKDIR}/git/"
+inherit cmake systemd