summaryrefslogtreecommitdiff
path: root/meta-openbmc-mods/meta-common/recipes-phosphor
diff options
context:
space:
mode:
authorEd Tanous <ed.tanous@intel.com>2019-02-14 03:51:50 +0300
committerEd Tanous <ed.tanous@intel.com>2019-03-13 00:58:57 +0300
commita7715486507e75e4a7cee843a48067b15595defa (patch)
tree9fd209d468c42cfb6553a50e2523c1d7e1fb120a /meta-openbmc-mods/meta-common/recipes-phosphor
parent9b44ea7e2de71224bce792654cab12b7a5ceaa7d (diff)
downloadopenbmc-a7715486507e75e4a7cee843a48067b15595defa.tar.xz
Initial commit of intel repository
Signed-off-by: Ed Tanous <ed.tanous@intel.com>
Diffstat (limited to 'meta-openbmc-mods/meta-common/recipes-phosphor')
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/configuration/entity-manager/xyz.openbmc_project.CloseMuxes.service10
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/configuration/entity-manager_%.bbappend18
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0002-Modify-Dbus-for-IPv6.patch55
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0003-Chassis-Power-Control-are-implemented.patch257
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0005-Add-DBUS-interface-of-CPU-and-Memory-s-properties.patch120
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0006-dbus-interface-add-boot-option-support-for-floppy-an.patch77
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0007-ipmi-set-BIOS-id.patch32
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0009-Add-host-restart-cause-property.patch98
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0010-Increase-the-default-watchdog-timeout-value.patch34
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0012-Add-RestoreDelay-interface-for-power-restore-delay.patch34
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0013-Add-ErrConfig.yaml-interface-for-processor-error-config.patch86
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0014-Add-multiple-state-signal-for-host-start-and-stop.patch63
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0016-Add-DBUS-interface-of-SMBIOS-MDR-V2.patch227
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0017-Add-shutdown-policy-interface-for-get-set-shutdown-p.patch42
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0018-Define-post-code-interfaces-for-post-code-manager.patch64
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces_%.bbappend16
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-mapper/xyz.openbmc_project.ObjectMapper.service20
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-mapper_%.bbappend1
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/fans/phosphor-pid-control/phosphor-pid-control.service12
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/fans/phosphor-pid-control_%.bbappend8
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0001-image_verify-Add-support-for-OpenSSL-1.1.0.patch130
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/fwupd@.service8
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager_%.bbappend11
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/gpiodaemon/gpiodaemon.bb18
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/host/obmc-op-control-host%.bbappend6
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/bmcweb.socket9
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb_%.bbappend1
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-channel-inventory%.bbappend4
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-channel-inventory%/channel.yaml8
-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.json49
-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/0002-Modify-dbus-interface-for-power-control.patch31
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0003-Modify-dbus-interface-for-chassis-control.patch33
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0009-IPv6-Network-changes.patch909
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0010-fix-get-system-GUID-ipmi-command.patch56
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0012-ipmi-set-get-boot-options.patch64
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0013-ipmi-add-set-bios-id-to-whitelist.patch25
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0014-Enable-get-device-guid-ipmi-command.patch45
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0016-add-better-sdbusplus-exception-handling.patch153
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0018-Catch-sdbusplus-exceptions-in-IPMI-net.patch49
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0021-Implement-IPMI-Commmand-Get-Host-Restart-Cause.patch143
-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/0048-Implement-IPMI-Master-Write-Read-command.patch322
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0049-Fix-Unspecified-error-on-ipmi-restart-cause-command.patch71
-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/0051-Fix-Set-LAN-Config-to-work-without-SetInProgress.patch142
-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/phosphor-ipmi-host.service26
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host_%.bbappend29
-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/org.openbmc.HostIpmi.SMM.service13
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-kcs/org.openbmc.HostIpmi.service13
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-kcs_%.bbappend9
-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/0007-Adding-support-for-GetSessionInfo-command.patch421
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-net/0008-Sync-GetSession-Info-cmd-based-on-Upstream-review.patch318
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-net_%.bbappend13
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-node-manager-proxy_git.bb19
-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
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/leds/intel-led-manager-config-native.bb21
-rwxr-xr-xmeta-openbmc-mods/meta-common/recipes-phosphor/leds/intel-led-manager-config/led.yaml36
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/logging/phosphor-logging_%.bbappend2
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/sel-logger/phosphor-sel-logger_%.bbappend6
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/selftest/intel-self-test/xyz.openbmc_project.selftest.service10
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/selftest/intel-self-test_git.bb38
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/sensors/dbus-sensors_%.bbappend8
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/settings/phosphor-settings-defaults-native.bbappend4
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/settings/phosphor-settings-defaults-native/defaults.yaml181
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/settings/phosphor-settings-manager/0001-settings-initialize-data-file-with-default-setting.patch37
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/settings/phosphor-settings-manager_%.bbappend4
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/srvcfg-manager/srvcfg-manager_git.bb28
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/state/phosphor-state-manager/0001-Modify-dbus-interface-for-power-control.patch38
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/state/phosphor-state-manager/0002-Capture-host-restart-cause.patch192
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/state/phosphor-state-manager/phosphor-reboot-host@.service18
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/state/phosphor-state-manager/phosphor-reset-host-check@.service19
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/state/phosphor-state-manager/phosphor-reset-host-reboot-attempts@.service14
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/state/phosphor-state-manager_%.bbappend8
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/system/callback-manager.bb19
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/system/obmc-mgr-system%.bbappend2
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/users/phosphor-user-manager/0005-Added-suport-for-multiple-user-manager-services.patch1648
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/users/phosphor-user-manager_%.bbappend5
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/frb2-watchdog.bb35
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/frb2-watchdog/.clang-format98
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/frb2-watchdog/CMakeLists.txt52
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/frb2-watchdog/cmake-format.json12
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/frb2-watchdog/frb2-watchdog.cpp258
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/phosphor-watchdog/obmc-enable-host-watchdog@.service14
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/phosphor-watchdog_%.bbappend4
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/system-watchdog.bb13
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/system-watchdog/obmc/system-watchdog/system-watchdog.conf3
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/system-watchdog/system-watchdog.service11
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/webui/phosphor-webui/0001-Implement-KVM-in-webui.patch242
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/webui/phosphor-webui_%.bbappend3
100 files changed, 7949 insertions, 0 deletions
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/configuration/entity-manager/xyz.openbmc_project.CloseMuxes.service b/meta-openbmc-mods/meta-common/recipes-phosphor/configuration/entity-manager/xyz.openbmc_project.CloseMuxes.service
new file mode 100644
index 000000000..bc05fa1a1
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/configuration/entity-manager/xyz.openbmc_project.CloseMuxes.service
@@ -0,0 +1,10 @@
+[Unit]
+Description=Close Muxes
+ConditionFileNotEmpty=/usr/bin/CloseMuxes.py
+
+[Service]
+ExecStart=/usr/bin/env CloseMuxes.py
+Type=oneshot
+
+[Install]
+WantedBy=basic.target
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/configuration/entity-manager_%.bbappend b/meta-openbmc-mods/meta-common/recipes-phosphor/configuration/entity-manager_%.bbappend
new file mode 100644
index 000000000..2ae5eeb64
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/configuration/entity-manager_%.bbappend
@@ -0,0 +1,18 @@
+# this is here just to bump faster than upstream
+SRC_URI = "git://github.com/openbmc/entity-manager.git"
+SRCREV = "9945ddffc67a9e564a92a3c0bddf2a2d7dc70b97"
+
+FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
+
+RDEPENDS_${PN} += "python"
+SRC_URI += " file://xyz.openbmc_project.CloseMuxes.service"
+SYSTEMD_SERVICE_${PN} += " xyz.openbmc_project.CloseMuxes.service"
+
+EXTRA_OECMAKE = "-DYOCTO=1 -DUSE_OVERLAYS=0"
+
+do_install_prepend() {
+ install -d ${D}${bindir}
+ install -m 0755 ${S}/scripts/CloseMuxes.py ${D}${bindir}
+ install -d ${D}${base_libdir}/systemd/system
+ install -m 0644 ${WORKDIR}/xyz.openbmc_project.CloseMuxes.service ${D}${base_libdir}/systemd/system
+}
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0002-Modify-Dbus-for-IPv6.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0002-Modify-Dbus-for-IPv6.patch
new file mode 100644
index 000000000..5b86d3154
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0002-Modify-Dbus-for-IPv6.patch
@@ -0,0 +1,55 @@
+From 066ecddebc29a87b05f8c66491eec19bb27d1d33 Mon Sep 17 00:00:00 2001
+From: David Cobbley <david.j.cobbley@linux.intel.com>
+Date: Wed, 6 Jun 2018 10:11:58 -0700
+Subject: [PATCH 3/3] Modify Dbus for IPv6.
+
+Add additional interfaces for IPv6 use.
+---
+ .../Network/EthernetInterface.interface.yaml | 18 ++++++++++++++++++
+ xyz/openbmc_project/Network/IP.interface.yaml | 4 ++++
+ 2 files changed, 22 insertions(+)
+
+diff --git a/xyz/openbmc_project/Network/EthernetInterface.interface.yaml b/xyz/openbmc_project/Network/EthernetInterface.interface.yaml
+index fc744fc..fd19e27 100644
+--- a/xyz/openbmc_project/Network/EthernetInterface.interface.yaml
++++ b/xyz/openbmc_project/Network/EthernetInterface.interface.yaml
+@@ -37,3 +37,21 @@ properties:
+ Implementation of this Dbus-interface is required to implement this property.
+ This property supports read/write operation.
+ Configure the NTP servers on the system during write operation.
++ - name: IPv6AcceptRA
++ type: boolean
++ description: >
++ Boolean for accepting router advertisements in IPv6
++ - name: IPAddressEnables
++ type: enum[self.IPAllowed]
++ description: >
++ The type of IP connection is allowed on this channel
++
++enumerations:
++ - name: IPAllowed
++ description: >
++ Determines whether the system allows both IPv6 & IPv4, or disables on
++ or the other
++ values:
++ - name: IPv4AndIPv6
++ - name: IPv4Only
++ - name: IPv6Only
+diff --git a/xyz/openbmc_project/Network/IP.interface.yaml b/xyz/openbmc_project/Network/IP.interface.yaml
+index 565dcd6..2ffb016 100644
+--- a/xyz/openbmc_project/Network/IP.interface.yaml
++++ b/xyz/openbmc_project/Network/IP.interface.yaml
+@@ -22,6 +22,10 @@ properties:
+ type: string
+ description: >
+ This is the IP gateway for this address.
++ - name: BackupGateway
++ type: string
++ description: >
++ This is the IP address of the backup gateway.
+ - name: Type
+ type: enum[self.Protocol]
+ description: >
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0003-Chassis-Power-Control-are-implemented.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0003-Chassis-Power-Control-are-implemented.patch
new file mode 100644
index 000000000..79d02ca9b
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0003-Chassis-Power-Control-are-implemented.patch
@@ -0,0 +1,257 @@
+From 35271230690c5d85dc7a6502031b38d93ddd683f Mon Sep 17 00:00:00 2001
+From: Ed Tanous <ed.tanous@intel.com>
+Date: Thu, 24 Jan 2019 09:29:01 -0800
+Subject: [PATCH] Chassis Power Control are implemented.
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Feature level:
+Power on server is ready
+Power off server is ready
+Power cycle server is ready
+Power reset server is ready
+
+Framework level:
+WebUI is enabled.
+IPMI Commands is enabled.
+Restful API is enabled.
+Physical buttons (Power/Reset/ID) are enabled.
+Chassis state manager is enabled.
+Host state manager is enabled.
+
+Enabled IPMI commands:
+ipmitool -H <ip_addr> -P <pass_word> -I lanplus chassis status
+ipmitool -H <ip_addr>  -P <pass_word> -I lanplus chassis power status
+ipmitool -H <ip_addr>  -P <pass_word> -I lanplus chassis power on
+ipmitool -H <ip_addr>  -P <pass_word> -I lanplus chassis power off
+ipmitool -H <ip_addr>  -P <pass_word> -I lanplus chassis power cycle
+ipmitool -H <ip_addr>  -P <pass_word> -I lanplus chassis power reset
+
+Enabled Restful APIs:
+Login: curl --noproxy <ip_addr> -c cjar -b cjar -k -H "Content-Type: application/json" -X POST https://<ip_addr>/login -d "{\"data\": [ \"root\", \"0penBmc\" ] }“
+Host State: curl --noproxy <ip_addr> -b cjar -k https://<ip_addr>/xyz/openbmc_project/state/host0
+Chassis State: curl --noproxy <ip_addr> -b cjar -k https://<ip_addr>/xyz/openbmc_project/state/chassis0
+Power state: curl --noproxy <ip_addr> -b cjar -k https://<ip_addr>/xyz/openbmc_project/Chassis/Control/Power0
+Power on/off: curl --noproxy <ip_addr> -q1c cjar -b cjar -k -H "Content-Type: application/json" -d '{"data": "xyz.openbmc_project.State.Host.Transition.Off"}' -X PUT https://<ip_addr>/xyz/openbmc_project/state/host0/attr/RequestedHostTransition
+
+Signed-off-by: Kuiying Wang <kuiying.wang@intel.com>
+Signed-off-by: Yong Li <yong.b.li@linux.intel.com>
+---
+ .../Chassis/Control/Chassis.interface.yaml | 94 +++++++++++++++++++
+ .../Chassis/Control/Power.interface.yaml | 85 ++++++++++++++---
+ 2 files changed, 166 insertions(+), 13 deletions(-)
+ create mode 100644 xyz/openbmc_project/Chassis/Control/Chassis.interface.yaml
+
+diff --git a/xyz/openbmc_project/Chassis/Control/Chassis.interface.yaml b/xyz/openbmc_project/Chassis/Control/Chassis.interface.yaml
+new file mode 100644
+index 0000000..c28492a
+--- /dev/null
++++ b/xyz/openbmc_project/Chassis/Control/Chassis.interface.yaml
+@@ -0,0 +1,94 @@
++description: >
++ chassis control service
++methods:
++ - name: powerOn
++ description: >
++ Power on system.
++ returns:
++ - name: state
++ type: int32
++ description: >
++ The result of command.
++ errors:
++ - xyz.openbmc_project.Chassis.Common.Error.UnsupportedCommand
++
++ - xyz.openbmc_project.Chassis.Common.Error.IOError
++
++ - name: powerOff
++ description: >
++ Power Off system.
++ returns:
++ - name: state
++ type: int32
++ description: >
++ The result of command.
++ errors:
++ - xyz.openbmc_project.Chassis.Common.Error.UnsupportedCommand
++
++ - xyz.openbmc_project.Chassis.Common.Error.IOError
++
++ - name: softPowerOff
++ description: >
++ Soft Power off system.
++ returns:
++ - name: state
++ type: int32
++ description: >
++ The result of command.
++ errors:
++ - xyz.openbmc_project.Chassis.Common.Error.UnsupportedCommand
++
++ - xyz.openbmc_project.Chassis.Common.Error.IOError
++
++ - name: reboot
++ description: >
++ reboot system.
++ returns:
++ - name: state
++ type: int32
++ description: >
++ The result of command.
++ errors:
++ - xyz.openbmc_project.Chassis.Common.Error.UnsupportedCommand
++
++ - xyz.openbmc_project.Chassis.Common.Error.IOError
++
++ - name: softReboot
++ description: >
++ Soft Reboot system.
++ returns:
++ - name: state
++ type: int32
++ description: >
++ The result of command.
++ errors:
++ - xyz.openbmc_project.Chassis.Common.Error.UnsupportedCommand
++
++ - xyz.openbmc_project.Chassis.Common.Error.IOError
++
++ - name: quiesce
++ description: >
++ Quiesce system.
++ returns:
++ - name: state
++ type: int32
++ description: >
++ The result of command.
++ errors:
++ - xyz.openbmc_project.Chassis.Common.Error.UnsupportedCommand
++
++ - xyz.openbmc_project.Chassis.Common.Error.IOError
++
++ - name: getPowerState
++ description: >
++ Get system power state.
++ returns:
++ - name: state
++ type: int32
++ description: >
++ The result of command.
++ errors:
++ - xyz.openbmc_project.Chassis.Common.Error.UnsupportedCommand
++
++ - xyz.openbmc_project.Chassis.Common.Error.IOError
++
+diff --git a/xyz/openbmc_project/Chassis/Control/Power.interface.yaml b/xyz/openbmc_project/Chassis/Control/Power.interface.yaml
+index 082586f..e77598b 100644
+--- a/xyz/openbmc_project/Chassis/Control/Power.interface.yaml
++++ b/xyz/openbmc_project/Chassis/Control/Power.interface.yaml
+@@ -1,31 +1,90 @@
+ description: >
+- Power control service
++ Chassis control service
+ methods:
++ - name: setPowerState
++ description: >
++ set host power state.
++ parameters:
++ - name: state
++ type: int32
++ description: >
++ 0 for force power off host
++ 1 for power on host
++ returns:
++ - name: status
++ type: int32
++ description: >
++ The result of command.
++ errors:
++ - xyz.openbmc_project.Chassis.Common.Error.UnsupportedCommand
++
++ - xyz.openbmc_project.Chassis.Common.Error.IOError
++
++ - name: getPowerState
++ description: >
++ Get current host power status.
++ returns:
++ - name: status
++ type: int32
++ description: >
++ Current host status,
++ 0 for host power off
++ 1 for host power on
++ errors:
++ - xyz.openbmc_project.Chassis.Common.Error.UnsupportedCommand
++
++ - xyz.openbmc_project.Chassis.Common.Error.IOError
++
+ - name: forcePowerOff
+ description: >
+ Force power off the host.
+ returns:
+ - name: status
+- type: boolean
++ type: int32
+ description: >
+ The result of power off command.
+ errors:
+ - xyz.openbmc_project.Chassis.Common.Error.UnsupportedCommand
++
+ - xyz.openbmc_project.Chassis.Common.Error.IOError
+
+ properties:
+- - name: PGood
+- type: boolean
+- default: false
++ - name: vrd_good
++ type: int32
++ default: 0
+ description: >
+- PSU Power good property
+- It is a read-only property.
+- - name: State
++ ACPI status
++ - name: s4s5_state
+ type: int32
+ default: 0
+ description: >
+- System power status
+- 0: power is off
+- 1: power is on
+- Setting its value to change the system state
+- Read its value to get the system state.
+\ No newline at end of file
++ ACPI status
++ - name: pgood
++ type: int32
++ default: 0
++ description: >
++ pgood property
++ - name: state
++ type: int32
++ default: 0
++ description: >
++ state property
++ - name: pgood_timeout
++ type: int32
++ default: 0
++ description: >
++ pgoodtimeout property
++ - name: post_complete
++ type: boolean
++ default: false
++ description: >
++ The current BIOS POST state,
++ false means not completed or system reset,
++ true means BIOS POST completed.
++signals:
++ - name: PowerGood
++ description: >
++ Signal for powergood
++ - name: PowerLost
++ description: >
++ Signal for powerlost
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0005-Add-DBUS-interface-of-CPU-and-Memory-s-properties.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0005-Add-DBUS-interface-of-CPU-and-Memory-s-properties.patch
new file mode 100644
index 000000000..7568f8ce9
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0005-Add-DBUS-interface-of-CPU-and-Memory-s-properties.patch
@@ -0,0 +1,120 @@
+From a30a09f58b9ebfb267c0b9cce9ae25994ea025ca Mon Sep 17 00:00:00 2001
+From: cyang29 <cheng.c.yang@intel.com>
+Date: Tue, 17 Jul 2018 16:04:58 +0800
+Subject: [PATCH] Add DBUS interface of CPU and Memory's properties Feature
+ Support: SMBIOS service interface. CPU DIMM information redfish
+ interface. Base on smbios spec DSP0134_3.0.0
+
+Signed-off-by: cyang29 <cheng.c.yang@intel.com>
+---
+ .../Inventory/Item/Cpu.interface.yaml | 41 +++++++++++++++++++
+ .../Inventory/Item/Dimm.interface.yaml | 46 +++++++++++++++++++++-
+ 2 files changed, 86 insertions(+), 1 deletion(-)
+
+diff --git a/xyz/openbmc_project/Inventory/Item/Cpu.interface.yaml b/xyz/openbmc_project/Inventory/Item/Cpu.interface.yaml
+index ab29cf3..313eada 100644
+--- a/xyz/openbmc_project/Inventory/Item/Cpu.interface.yaml
++++ b/xyz/openbmc_project/Inventory/Item/Cpu.interface.yaml
+@@ -1,4 +1,45 @@
+ description: >
+ Implement to provide CPU attributes.
++properties:
++ - name: ProcessorSocket
++ type: string
++ description: >
++ Processor Socket on MotherBoard
++ - name: ProcessorType
++ type: string
++ description: >
++ Processor Type of CPU
++ - name: ProcessorFamily
++ type: string
++ description: >
++ Processor Family of CPU
++ - name: ProcessorManufacturer
++ type: string
++ description: >
++ Processor Manufacturer of CPU
++ - name: ProcessorId
++ type: uint32
++ description: >
++ Processor ID of CPU
++ - name: ProcessorVersion
++ type: string
++ description: >
++ Processor Version of CPU
++ - name: ProcessorMaxSpeed
++ type: uint16
++ description: >
++ Max Speed CPU Can Support
++ - name: ProcessorCharacteristics
++ type: string
++ description: >
++ The Characteristics CPU Has
++ - name: ProcessorCoreCount
++ type: uint16
++ description: >
++ The Count of Core in CPU
++ - name: ProcessorThreadCount
++ type: uint16
++ description: >
++ The Count of Thread CPU Can Support
+
+ # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
+diff --git a/xyz/openbmc_project/Inventory/Item/Dimm.interface.yaml b/xyz/openbmc_project/Inventory/Item/Dimm.interface.yaml
+index d85326d..b750320 100644
+--- a/xyz/openbmc_project/Inventory/Item/Dimm.interface.yaml
++++ b/xyz/openbmc_project/Inventory/Item/Dimm.interface.yaml
+@@ -1,4 +1,48 @@
+ description: >
+ Implement to provide DIMM attributes.
+-
++properties:
++ - name: MemoryDataWidth
++ type: uint16
++ description: >
++ Data width of Memory.
++ - name: MemorySizeInKB
++ type: uint32
++ description: >
++ Memory size of DIMM in Kilobyte.
++ - name: MemoryDeviceLocator
++ type: string
++ description: >
++ Socket on base board where Memory located.
++ - name: MemoryType
++ type: string
++ description: >
++ Type of memory.
++ - name: MemoryTypeDetail
++ type: string
++ description: >
++ Additional detail on Memory.
++ - name: MemorySpeed
++ type: uint16
++ description: >
++ The maximun capable speed of Memory.
++ - name: MemoryManufacturer
++ type: string
++ description: >
++ Manufacturer of memory.
++ - name: MemorySerialNum
++ type: string
++ description: >
++ Memory Serial Number.
++ - name: MemoryPartNum
++ type: string
++ description: >
++ Memory Part Number.
++ - name: MemoryAttributes
++ type: byte
++ description: >
++ Rank attributes of Memory.
++ - name: MemoryConfClockSpeed
++ type: uint16
++ description: >
++ Configured clock speed to Memory.
+ # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
+--
+2.16.2
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0006-dbus-interface-add-boot-option-support-for-floppy-an.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0006-dbus-interface-add-boot-option-support-for-floppy-an.patch
new file mode 100644
index 000000000..f0d7b03f8
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0006-dbus-interface-add-boot-option-support-for-floppy-an.patch
@@ -0,0 +1,77 @@
+From 643772fc7f6021fbfba3b14de0c86501ae3e7f3a Mon Sep 17 00:00:00 2001
+From: "Jia, Chunhui" <chunhui.jia@intel.com>
+Date: Fri, 13 Jul 2018 15:22:05 +0800
+Subject: [PATCH] [dbus interface]add boot option support for floppy and USB
+
+Current implementations use ExternalMedia type to specify both CD/DVD/USB
+/Floppy. But in IPMI spec, they are different. CD/DVD type is 0x5 and
+USB/Floppy type is 0xF.
+
+This causes a bug that we can not force BIOS boots into USB/Floppy.
+
+Test:
+$ ipmitool -H 10.239.56.91 -P 0penBmc -I lanplus raw
+ 0x0 0x8 0x5 0x80 0x14 0x00 0x00 0x00
+$ ipmitool -H 10.239.56.91 -P 0penBmc -I lanplus chassis bootparam get 5
+Boot parameter version: 1
+Boot parameter 5 is valid/unlocked
+Boot parameter data: 8014000000
+ Boot Flags :
+ - Boot Flag Valid
+ - Options apply to only next boot
+ - BIOS PC Compatible (legacy) boot
+ - Boot Device Selector : Force Boot from CD/DVD
+ - Console Redirection control : System Default
+ - BIOS verbosity : Console redirection occurs per BIOS
+ configuration setting (default)
+ - BIOS Mux Control Override :
+ BIOS uses recommended setting of the mux at the end of POST
+
+$ipmitool -H 10.239.56.91 -P 0penBmc -I lanplus raw
+ 0x0 0x8 0x5 0x80 0x3c 0x00 0x00 0x00
+$ipmitool -H 10.239.56.91 -P 0penBmc -I lanplus chassis bootparam get 5
+Boot parameter version: 1
+Boot parameter 5 is valid/unlocked
+Boot parameter data: 803c000000
+ Boot Flags :
+ - Boot Flag Valid
+ - Options apply to only next boot
+ - BIOS PC Compatible (legacy) boot
+ - Boot Device Selector : Force Boot from Floppy/primary removable media
+ - Console Redirection control : System Default
+ - BIOS verbosity :
+ Console redirection occurs per BIOS configuration setting (default)
+
+ - BIOS Mux Control Override :
+ BIOS uses recommended setting of the mux at the end of POST
+
+Signed-off-by: Jia, Chunhui <chunhui.jia@intel.com>
+---
+ xyz/openbmc_project/Control/Boot/Source.interface.yaml | 7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+diff --git a/xyz/openbmc_project/Control/Boot/Source.interface.yaml b/xyz/openbmc_project/Control/Boot/Source.interface.yaml
+index ea811bd..8e5916f 100644
+--- a/xyz/openbmc_project/Control/Boot/Source.interface.yaml
++++ b/xyz/openbmc_project/Control/Boot/Source.interface.yaml
+@@ -15,12 +15,15 @@ enumerations:
+ - name: Disk
+ description: >
+ Boot from the local hard disk.
+- - name: ExternalMedia
++ - name: DVD
+ description: >
+- Boot from CD/DVD/USB, etc.
++ Boot from CD/DVD.
+ - name: Network
+ description: >
+ Boot from a remote source over a network.
+ - name: Default
+ description: >
+ Boot from an implementation defined source.
++ - name: Removable
++ description: >
++ Boot from floppy/primary removable media(USB).
+--
+2.16.2
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0007-ipmi-set-BIOS-id.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0007-ipmi-set-BIOS-id.patch
new file mode 100644
index 000000000..c87b2d89d
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0007-ipmi-set-BIOS-id.patch
@@ -0,0 +1,32 @@
+From 49debd0955b672d591f35e74119b288bd6df2992 Mon Sep 17 00:00:00 2001
+From: "Jia, Chunhui" <chunhui.jia@intel.com>
+Date: Tue, 24 Jul 2018 11:40:49 +0800
+Subject: [PATCH] [ipmi] set BIOS id
+
+change#2
+add new dbus interface for BIOS attributes
+
+Signed-off-by: Jia, Chunhui <chunhui.jia@intel.com>
+---
+ xyz/openbmc_project/Inventory/Item/Bios.interface.yaml | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+ create mode 100644 xyz/openbmc_project/Inventory/Item/Bios.interface.yaml
+
+diff --git a/xyz/openbmc_project/Inventory/Item/Bios.interface.yaml b/xyz/openbmc_project/Inventory/Item/Bios.interface.yaml
+new file mode 100644
+index 0000000..d7a6b95
+--- /dev/null
++++ b/xyz/openbmc_project/Inventory/Item/Bios.interface.yaml
+@@ -0,0 +1,9 @@
++description: >
++ Implement to provide BIOS attributes.
++properties:
++ - name: BiosId
++ type: string
++ description: >
++ BIOS ID (version) string
++
++# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
+--
+2.16.2
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0009-Add-host-restart-cause-property.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0009-Add-host-restart-cause-property.patch
new file mode 100644
index 000000000..1221a0ab4
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0009-Add-host-restart-cause-property.patch
@@ -0,0 +1,98 @@
+From 72b7b30a5dda56c170ee2ce82c1082c26f4663e3 Mon Sep 17 00:00:00 2001
+From: Kuiying Wang <kuiying.wang@intel.com>
+Date: Tue, 31 Jul 2018 16:55:21 +0800
+Subject: [PATCH] Add host restart cause property.
+
+Add host restart cause property to track the information about what
+action last caused the system to restart.
+According to IPMI Spec, it includes 12 types as following:
+1. Unknown 0x0
+2. IpmiCommand 0x1
+3. ResetButton 0x2
+4. PowerButton 0x3
+5. WatchdogTimer 0x4
+6. OEM 0x5
+7. PowerPolicyAlwaysOn 0x6
+8. PowerPolicyPreviousState 0x7
+9. PEF-Reset 0x8
+10. PEF-PowerCycle 0x9
+11. SoftReset 0xA
+12. RTC-Wakeup 0xB
+
+Change-Id: Id2cc6a18b98e485a978940e5ffc085bf5c4fbed8
+Signed-off-by: Kuiying Wang <kuiying.wang@intel.com>
+---
+ xyz/openbmc_project/State/Host.interface.yaml | 52 +++++++++++++++++++
+ 1 file changed, 52 insertions(+)
+
+diff --git a/xyz/openbmc_project/State/Host.interface.yaml b/xyz/openbmc_project/State/Host.interface.yaml
+index 8f481b8..a4d88d0 100644
+--- a/xyz/openbmc_project/State/Host.interface.yaml
++++ b/xyz/openbmc_project/State/Host.interface.yaml
+@@ -17,6 +17,12 @@ properties:
+ comparing the CurrentHostState and the RequestedHostTransition
+ properties.
+
++ - name: HostRestartCause
++ type: enum[self.RestartCause]
++ default: Unknown
++ description: >
++ The information about what action last caused the system to restart.
++
+ enumerations:
+ - name: Transition
+ description: >
+@@ -45,3 +51,49 @@ enumerations:
+ - name: 'Quiesced'
+ description: >
+ Host firmware is quiesced
++
++ - name: RestartCause
++ description: >
++ The information about what action last caused the system to restart.
++ values:
++ - name: Unknown
++ description: >
++ System start/restart detected but the reason is unknown.
++ - name: IpmiCommand
++ description: >
++ System start/restart detected and caused by ipmi command.
++ - name: ResetButton
++ description: >
++ System start/restart detected and caused by reset button.
++ - name: PowerButton
++ description: >
++ System start/restart detected and caused by power button.
++ - name: WatchdogTimer
++ description: >
++ System start/restart detected and casued by watchdog expiration.
++ - name: OEM
++ description: >
++ System start/restart detected and caused by OEM command.
++ - name: PowerPolicyAlwaysOn
++ description: >
++ System start/restart detected and caused by power restore policy
++ "chassis always powers up after AC/mains is applied or returns".
++ - name: PowerPolicyPreviousState
++ description: >
++ System start/restart detected and caused by power restore policy
++ "after AC/mains is applied or returns, power is restored to the
++ state was in effect when AC/mains removed or lost".
++ - name: PEFReset
++ description: >
++ System start/restart detected and caused by PEF(reset).
++ - name: PEFPowerCycle
++ description: >
++ System start/restart detected and caused by PEF(power-cycle).
++ - name: SoftReset
++ description: >
++ System start/restart detected and caused by soft reset like
++ "CTRL-ALT-DEL".
++ - name: RTCWakeup
++ description: >
++ System start/restart detected and caused by system real time
++ clock(RTC) wakeup.
+\ No newline at end of file
+--
+2.17.0
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0010-Increase-the-default-watchdog-timeout-value.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0010-Increase-the-default-watchdog-timeout-value.patch
new file mode 100644
index 000000000..2c9344306
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0010-Increase-the-default-watchdog-timeout-value.patch
@@ -0,0 +1,34 @@
+From 631deef0ca88a77283741edeae8078d2185f414c Mon Sep 17 00:00:00 2001
+From: Yong Li <yong.b.li@linux.intel.com>
+Date: Fri, 10 Aug 2018 16:23:13 +0800
+Subject: [PATCH] Increase the default watchdog timeout value
+
+The default timeout for poweron is 30 seconds,
+but currently the host power on needs 120+ seconds
+due to unimplemented ipmi commands for BIOS.
+
+Increase the value as a workaround,
+to avoid the watchdog timeout during power on.
+Will adjust this value in the future
+
+Signed-off-by: Yong Li <yong.b.li@linux.intel.com>
+---
+ xyz/openbmc_project/State/Watchdog.interface.yaml | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/xyz/openbmc_project/State/Watchdog.interface.yaml b/xyz/openbmc_project/State/Watchdog.interface.yaml
+index f76dbf2..402e1a8 100644
+--- a/xyz/openbmc_project/State/Watchdog.interface.yaml
++++ b/xyz/openbmc_project/State/Watchdog.interface.yaml
+@@ -37,7 +37,7 @@ properties:
+ type: uint64
+ description: >
+ Time interval to arm the watchdog, in milli-second.
+- default: 30000
++ default: 600000
+ - name: TimeRemaining
+ type: uint64
+ description: >
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0012-Add-RestoreDelay-interface-for-power-restore-delay.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0012-Add-RestoreDelay-interface-for-power-restore-delay.patch
new file mode 100644
index 000000000..9052435ca
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0012-Add-RestoreDelay-interface-for-power-restore-delay.patch
@@ -0,0 +1,34 @@
+From eeac4cf4528994aeb213d549daf4c033ac9d3bbc Mon Sep 17 00:00:00 2001
+From: Kuiying Wang <kuiying.wang@intel.com>
+Date: Fri, 24 Aug 2018 17:55:35 +0800
+Subject: [PATCH] Add RestoreDelay interface for power restore delay
+
+Which provide one property "PowerRestoreDelay"
+
+Change-Id: I4e6d3e45948b1e288301b4aa52cc08cace4f1bc2
+Signed-off-by: Kuiying Wang <kuiying.wang@intel.com>
+---
+ .../Control/Power/RestoreDelay.interface.yaml | 11 +++++++++++
+ 1 file changed, 11 insertions(+)
+ create mode 100644 xyz/openbmc_project/Control/Power/RestoreDelay.interface.yaml
+
+diff --git a/xyz/openbmc_project/Control/Power/RestoreDelay.interface.yaml b/xyz/openbmc_project/Control/Power/RestoreDelay.interface.yaml
+new file mode 100644
+index 0000000..55ee80a
+--- /dev/null
++++ b/xyz/openbmc_project/Control/Power/RestoreDelay.interface.yaml
+@@ -0,0 +1,11 @@
++description: >
++ Implement to specify power transition behavior on a BMC reset.
++ The implementation based on restore policy and set a delay time
++ for power restore.
++
++properties:
++ - name: PowerRestoreDelay
++ type: uint16
++ description: >
++ The delay time for power restore.
++ Power Restore Delay is NOT applied on power policy is "Always Off"
+--
+2.17.0
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0013-Add-ErrConfig.yaml-interface-for-processor-error-config.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0013-Add-ErrConfig.yaml-interface-for-processor-error-config.patch
new file mode 100644
index 000000000..9471c7ab2
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0013-Add-ErrConfig.yaml-interface-for-processor-error-config.patch
@@ -0,0 +1,86 @@
+From 7260c24b201759f3a5168eebfee215072c13e641 Mon Sep 17 00:00:00 2001
+From: Kuiying Wang <kuiying.wang@intel.com>
+Date: Thu, 30 Aug 2018 16:22:43 +0800
+Subject: [PATCH] Add ErrConfig.yaml interface for processor error
+ configuration.
+
+Which provide 3 properties:
+ ResetCfg
+ type: byte
+ description: >
+ Reset Configuration
+ [0]: CATERR Reset Enabled
+ 0b: Disabled
+ 1b: Enabled
+ [1]: ERR2 Reset Enabled
+ 0b: Disabled
+ 1b: Enabled
+ [7:2]: Reserved
+ ResetErrorOccurrenceCounts
+ type: byte
+ description: >
+ Reset Error Occurrence Counts
+ [0]: Reset CPU Error Counts
+ 0b: Keep CPU Error Counts
+ 1b: Reset all CPU Error Counts to zero
+ [7:1]: Reserved
+ CATERRStatus
+ type: array[byte]
+ description: >
+ For all CPUs including the non-legacy socket CPU
+ CPU CATERR (Core Error) occurrence
+ [5:0]: Error Occurrence Count
+ [7:6]: CPU Status
+ 00b: Disabled
+ 01b: Enabled
+ 11b: Not Present
+
+Change-Id: Ibc5a7a5e15c998e56c04e23b1043d99243a91171
+Signed-off-by: Kuiying Wang <kuiying.wang@intel.com>
+---
+ .../Processor/ErrConfig.interface.yaml | 33 +++++++++++++++++++
+ 1 file changed, 33 insertions(+)
+ create mode 100644 xyz/openbmc_project/Control/Processor/ErrConfig.interface.yaml
+
+diff --git a/xyz/openbmc_project/Control/Processor/ErrConfig.interface.yaml b/xyz/openbmc_project/Control/Processor/ErrConfig.interface.yaml
+new file mode 100644
+index 0000000..2304263
+--- /dev/null
++++ b/xyz/openbmc_project/Control/Processor/ErrConfig.interface.yaml
+@@ -0,0 +1,33 @@
++description: >
++ This defines processor error configuration.
++properties:
++ - name: ResetCfg
++ type: byte
++ description: >
++ Reset Configuration
++ [0]: CATERR Reset Enabled
++ 0b: Disabled
++ 1b: Enabled
++ [1]: ERR2 Reset Enabled
++ 0b: Disabled
++ 1b: Enabled
++ [7:2]: Reserved
++
++ - name: ResetErrorOccurrenceCounts
++ type: byte
++ description: >
++ Reset Error Occurrence Counts
++ [0]: Reset CPU Error Counts
++ 0b: Keep CPU Error Counts
++ 1b: Reset all CPU Error Counts to zero
++ [7:1]: Reserved
++ - name: CATERRStatus
++ type: array[byte]
++ description: >
++ For all CPUs including the non-legacy socket CPU
++ CPU CATERR (Core Error) occurrence
++ [5:0]: Error Occurrence Count
++ [7:6]: CPU Status
++ 00b: Disabled
++ 01b: Enabled
++ 11b: Not Present
+--
+2.17.0
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0014-Add-multiple-state-signal-for-host-start-and-stop.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0014-Add-multiple-state-signal-for-host-start-and-stop.patch
new file mode 100644
index 000000000..a8d732dab
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0014-Add-multiple-state-signal-for-host-start-and-stop.patch
@@ -0,0 +1,63 @@
+From 6d0069f4a2b4637c58fd321c9db3034ac9dd17c7 Mon Sep 17 00:00:00 2001
+From: Kuiying Wang <kuiying.wang@intel.com>
+Date: Wed, 12 Sep 2018 15:03:26 +0800
+Subject: [PATCH] Add multiple state signal for host start and stop
+
+Add six host state signals like following:
+ - name: PreHostStart
+ description: >
+ This is the signal to indicate host is at pre start stage.
+ - name: PostHostStart
+ description: >
+ This is the signal to indicate host is at start complete stage.
+ - name: HostStarting
+ description: >
+ This is the signal to indicate host is at starting stage.
+ - name: HostStoping
+ description: >
+ This is the signal to indicate host is at stoping stage.
+ - name: PreHostStop
+ description: >
+ This is the signal to indicate host is at pre stop stage.
+ - name: PostHostStop
+ description: >
+ This is the signal to indicate host is at stop complete stage.
+
+Signed-off-by: Kuiying Wang <kuiying.wang@intel.com>
+---
+ xyz/openbmc_project/State/Host.interface.yaml | 21 ++++++++++++++++++++-
+ 1 file changed, 20 insertions(+), 1 deletion(-)
+
+diff --git a/xyz/openbmc_project/State/Host.interface.yaml b/xyz/openbmc_project/State/Host.interface.yaml
+index 8531a27..1ceba13 100644
+--- a/xyz/openbmc_project/State/Host.interface.yaml
++++ b/xyz/openbmc_project/State/Host.interface.yaml
+@@ -96,4 +96,23 @@ enumerations:
+ - name: RTCWakeup
+ description: >
+ System start/restart detected and caused by system real time
+- clock(RTC) wakeup.
+\ No newline at end of file
++ clock(RTC) wakeup.
++signals:
++ - name: PreHostStart
++ description: >
++ This is the signal to indicate host is at pre start stage.
++ - name: PostHostStart
++ description: >
++ This is the signal to indicate host is at start complete stage.
++ - name: HostStarting
++ description: >
++ This is the signal to indicate host is at starting stage.
++ - name: HostStoping
++ description: >
++ This is the signal to indicate host is at stoping stage.
++ - name: PreHostStop
++ description: >
++ This is the signal to indicate host is at pre stop stage.
++ - name: PostHostStop
++ description: >
++ This is the signal to indicate host is at stop complete stage.
+--
+2.16.2
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0016-Add-DBUS-interface-of-SMBIOS-MDR-V2.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0016-Add-DBUS-interface-of-SMBIOS-MDR-V2.patch
new file mode 100644
index 000000000..576bae81a
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0016-Add-DBUS-interface-of-SMBIOS-MDR-V2.patch
@@ -0,0 +1,227 @@
+From 9490574667485cd407193ff9f0d6a96f8c2c87d3 Mon Sep 17 00:00:00 2001
+From: cyang29 <cheng.c.yang@intel.com>
+Date: Wed, 12 Sep 2018 00:27:23 +0800
+Subject: [PATCH] Add DBUS interface of SMBIOS MDR V2
+
+Support:
+ SMBIOS MDR V2 service interface.
+ SMBIOS MDR V2 IPMI Command
+ SMBIOS MDR V2 Redfish interface.
+Base on SMBIOS spec DSP0134_3.0.0 and Managed Data Region
+Specification Revision 4
+---
+ xyz/openbmc_project/Smbios/MDR_V2.errors.yaml | 9 +
+ xyz/openbmc_project/Smbios/MDR_V2.interface.yaml | 158 +++++++++++++++++++++++
+ xyz/openbmc_project/Smbios/README.md | 21 +++
+ 3 files changed, 188 insertions(+)
+ create mode 100644 xyz/openbmc_project/Smbios/MDR_V2.errors.yaml
+ create mode 100644 xyz/openbmc_project/Smbios/MDR_V2.interface.yaml
+ create mode 100644 xyz/openbmc_project/Smbios/README.md
+
+diff --git a/xyz/openbmc_project/Smbios/MDR_V2.errors.yaml b/xyz/openbmc_project/Smbios/MDR_V2.errors.yaml
+new file mode 100644
+index 0000000..88bd6db
+--- /dev/null
++++ b/xyz/openbmc_project/Smbios/MDR_V2.errors.yaml
+@@ -0,0 +1,9 @@
++- name: InvalidParameter
++ description: >
++ An invalid parameter is attempted.
++- name: UpdateInProgress
++ description: >
++ Update is in progress.
++- name: InvalidId
++ description: >
++ An invalid Id is attempted.
+diff --git a/xyz/openbmc_project/Smbios/MDR_V2.interface.yaml b/xyz/openbmc_project/Smbios/MDR_V2.interface.yaml
+new file mode 100644
+index 0000000..f97700a
+--- /dev/null
++++ b/xyz/openbmc_project/Smbios/MDR_V2.interface.yaml
+@@ -0,0 +1,158 @@
++description: >
++ SMBIOS MDR V2 service
++methods:
++ - name: GetDirectoryInformation
++ description: >
++ Get the directory with directory index.
++ parameters:
++ - name: dirIndex
++ type: byte
++ description: >
++ Directory index of SMBIOS.
++ returns:
++ - name: dir
++ type: array[byte]
++ description: >
++ Directory of agent.
++ errors:
++ - self.Error.InvalidParameter
++
++ - name: GetDataInformation
++ description: >
++ Get the data info with id index and data set ID.
++ parameters:
++ - name: idIndex
++ type: byte
++ description: >
++ Index of SMBIOS directory.
++ returns:
++ - name: dataInfo
++ type: array[byte]
++ description: >
++ Data information of SMBIOS.
++ errors:
++ - self.Error.InvalidParameter
++
++ - name: SendDirectoryInformation
++ description: >
++ Send directory information to SMBIOS directory.
++ parameters:
++ - name: dirVersion
++ type: byte
++ description: >
++ A counter which increments each time directory updated.
++ - name: dirIndex
++ type: byte
++ description: >
++ Directory index of SMBIOS.
++ - name: returnedEntries
++ type: byte
++ description: >
++ Indicates number of directory entries.
++ - name: remainingEntries
++ type: byte
++ description: >
++ Remaining entries which are higher than index in this transfer.
++ - name: dirEntry
++ type: array[byte]
++ description: >
++ Data set ID of SMBIOS table.
++ returns:
++ - name: status
++ type: boolean
++ description: >
++ Need to continue directory transmisson or not.
++ errors:
++ - self.Error.InvalidParameter
++
++ - name: GetDataOffer
++ description: >
++ Get data set ID.
++ returns:
++ - name: offer
++ type: array[byte]
++ description: >
++ Data set ID.
++ errors:
++ - self.Error.UpdateInProgress
++
++ - name: SendDataInformation
++ description: >
++ Send data information with directory index.
++ parameters:
++ - name: idIndex
++ type: byte
++ description: >
++ Index of SMBIOS directory.
++ - name: flag
++ type: byte
++ description: >
++ Valid flag to set dir entry status.
++ - name: dataLen
++ type: uint32
++ description: >
++ The length of the data in bytes.
++ - name: dataVer
++ type: uint32
++ description: >
++ The version number of this data.
++ - name: timeStamp
++ type: uint32
++ description: >
++ Timestamp determinded by the agent.
++ returns:
++ - name: status
++ type: boolean
++ description: >
++ Whether data changes.
++ errors:
++ - self.Error.InvalidParameter
++
++ - name: FindIdIndex
++ description: >
++ Find id index by data info.
++ parameters:
++ - name: dataInfo
++ type: array[byte]
++ description: >
++ Data info of data entry.
++ returns:
++ - name: idIndex
++ type: int32
++ description: >
++ Id index of data entry.
++ errors:
++ - self.Error.InvalidId
++
++ - name: AgentSynchronizeData
++ description: >
++ Synchronize SMBIOS data from file.
++ returns:
++ - name: status
++ type: boolean
++ description: >
++ Whether synchronization succeed or not.
++
++ - name: SynchronizeDirectoryCommonData
++ description: >
++ Synchronize directory common data.
++ parameters:
++ - name: idIndex
++ type: byte
++ description: >
++ Index of SMBIOS directory.
++ - name: size
++ type: uint32
++ description: >
++ Size of data that BIOS prepare to transfer.
++ returns:
++ - name: commonData
++ type: array[uint32]
++ description: >
++ Directory common data includes data size, version and timestamp.
++
++properties:
++ - name: DirectoryEntries
++ type: byte
++ description: >
++ Numbers of directory entries.
+diff --git a/xyz/openbmc_project/Smbios/README.md b/xyz/openbmc_project/Smbios/README.md
+new file mode 100644
+index 0000000..415ac52
+--- /dev/null
++++ b/xyz/openbmc_project/Smbios/README.md
+@@ -0,0 +1,22 @@
++# SMBIOS MDR V2
++
++## Overview
++SMBIOS MDR V2 service exposes D-Bus methods for SMBIOS Version 2 operations.
++
++### SMBIOS MDR V2 Interface
++SMBIOS MDR V2 interface `xyz.openbmc_project.Smbios.MDR_V2` provides following
++methods.
++#### methods
++* GetDirectoryInformation - Get the directory with directory index.
++* GetDataInformation - Get the data information with id index and data set ID.
++* SendDirectoryInformation - Send directory information to SMBIOS directory.
++* GetDataOffer - Get data set ID.
++* SendDataInformation - Send data information with directory index.
++* FindIdIndex - Find id index by data info.
++* SynchronizeDirectoryCommonData - Synchronize directory common data before
++SMBIOS data start to transfer.
++* AgentSynchronizeData - Synchronize SMBIOS data from file after data transfer
++complete.
++
++#### properties
++* DirEntries - Numbers of directory entries. Default: 0
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0017-Add-shutdown-policy-interface-for-get-set-shutdown-p.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0017-Add-shutdown-policy-interface-for-get-set-shutdown-p.patch
new file mode 100644
index 000000000..587bcebf1
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0017-Add-shutdown-policy-interface-for-get-set-shutdown-p.patch
@@ -0,0 +1,42 @@
+From 7ebb72a93922a0163a5b35c277f3bbd241bdf78c Mon Sep 17 00:00:00 2001
+From: Yong Li <yong.b.li@linux.intel.com>
+Date: Mon, 22 Oct 2018 16:20:36 +0800
+Subject: [PATCH] Add shutdown policy interface for get/set shutdown policy OEM
+ IPMI commands
+
+The policy property is used to store the shutdown policy.
+
+Tested by:
+busctl get-property "xyz.openbmc_project.Settings" \
+"/xyz/openbmc_project/control/shutdown_policy_config" \
+"xyz.openbmc_project.Control.ShutdownPolicy" "Policy"
+
+busctl set-property "xyz.openbmc_project.Settings" \
+"/xyz/openbmc_project/control/shutdown_policy_config" \
+"xyz.openbmc_project.Control.ShutdownPolicy" "Policy" y 1
+
+Signed-off-by: Yong Li <yong.b.li@linux.intel.com>
+---
+ xyz/openbmc_project/Control/ShutdownPolicy.interface.yaml | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+ create mode 100644 xyz/openbmc_project/Control/ShutdownPolicy.interface.yaml
+
+diff --git a/xyz/openbmc_project/Control/ShutdownPolicy.interface.yaml b/xyz/openbmc_project/Control/ShutdownPolicy.interface.yaml
+new file mode 100644
+index 0000000..e562ea8
+--- /dev/null
++++ b/xyz/openbmc_project/Control/ShutdownPolicy.interface.yaml
+@@ -0,0 +1,10 @@
++description: >
++ An interface for node shutdown policy on multi-node products.
++properties:
++ - name: Policy
++ type: byte
++ description: >
++ 0: Do not shutdown node on a power supply over current(OC)
++ or a power supply over temperature(OT) event.
++ 1: Shutdown node on an OC/OT event.
++ Only available on multi-node products.
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0018-Define-post-code-interfaces-for-post-code-manager.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0018-Define-post-code-interfaces-for-post-code-manager.patch
new file mode 100644
index 000000000..ce23c222b
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0018-Define-post-code-interfaces-for-post-code-manager.patch
@@ -0,0 +1,64 @@
+From f88cac8364d5312e29208018909827d2da4a0f87 Mon Sep 17 00:00:00 2001
+From: Kuiying Wang <kuiying.wang@intel.com>
+Date: Tue, 19 Feb 2019 16:52:51 +0800
+Subject: [PATCH] Define post code interfaces for post code manager
+
+It includes one method and 2 properties.
+properties:
+ - name: CurrentBootCycleIndex
+ description: >
+ It is used to indicate current boot cycle index.
+ - name: MaxBootCycleNum
+ description: >
+ The max cached boot cycles for post code.
+methods:
+ - name: GetPostCodes
+ description: >
+ Method to get the cached post code for each boot cycle.
+TestBy: bitbake build
+
+Signeoff-by: Kuiying Wang <kuiying.wang@intel.com>
+---
+ .../State/Boot/PostCode.interface.yaml | 30 ++++++++++++++++++++++
+ 1 file changed, 30 insertions(+)
+ create mode 100644 xyz/openbmc_project/State/Boot/PostCode.interface.yaml
+
+diff --git a/xyz/openbmc_project/State/Boot/PostCode.interface.yaml b/xyz/openbmc_project/State/Boot/PostCode.interface.yaml
+new file mode 100644
+index 0000000..711749d
+--- /dev/null
++++ b/xyz/openbmc_project/State/Boot/PostCode.interface.yaml
+@@ -0,0 +1,30 @@
++description: >
++ Monitor Post code coming and buffer all of them based on boot cycle
++ into file system.
++
++properties:
++ - name: CurrentBootCycleIndex
++ type: uint16
++ description: >
++ It is used to indicate current boot cycle index.
++ - name: MaxBootCycleNum
++ type: uint16
++ description: >
++ The max cached boot cycles for post code.
++methods:
++ - name: GetPostCodes
++ description: >
++ Method to get the cached post code for each boot cycle.
++ parameters:
++ - name: Index
++ type: uint16
++ description: >
++ Index indicates which boot cycle of post codes is requested.
++ returns:
++ - name: codes
++ type: array[uint64]
++ description: >
++ An array of post codes of one boot cycle.
++ errors:
++ - xyz.openbmc_project.Common.Error.InternalFailure
++ - xyz.openbmc_project.Common.Error.InvalidArgument
+--
+2.16.2
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces_%.bbappend b/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces_%.bbappend
new file mode 100644
index 000000000..2449d9225
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces_%.bbappend
@@ -0,0 +1,16 @@
+FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
+
+SRC_URI += "file://0002-Modify-Dbus-for-IPv6.patch \
+ file://0003-Chassis-Power-Control-are-implemented.patch \
+ file://0005-Add-DBUS-interface-of-CPU-and-Memory-s-properties.patch \
+ file://0006-dbus-interface-add-boot-option-support-for-floppy-an.patch \
+ file://0007-ipmi-set-BIOS-id.patch \
+ file://0009-Add-host-restart-cause-property.patch \
+ file://0010-Increase-the-default-watchdog-timeout-value.patch \
+ file://0012-Add-RestoreDelay-interface-for-power-restore-delay.patch \
+ file://0013-Add-ErrConfig.yaml-interface-for-processor-error-config.patch \
+ file://0014-Add-multiple-state-signal-for-host-start-and-stop.patch \
+ file://0016-Add-DBUS-interface-of-SMBIOS-MDR-V2.patch \
+ file://0017-Add-shutdown-policy-interface-for-get-set-shutdown-p.patch \
+ file://0018-Define-post-code-interfaces-for-post-code-manager.patch \
+ "
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-mapper/xyz.openbmc_project.ObjectMapper.service b/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-mapper/xyz.openbmc_project.ObjectMapper.service
new file mode 100644
index 000000000..9af9af254
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-mapper/xyz.openbmc_project.ObjectMapper.service
@@ -0,0 +1,20 @@
+[Unit]
+Description=Phosphor DBus Service Discovery Manager
+Before=obmc-mapper.target
+After=dbus.socket
+
+[Service]
+Restart=always
+Type=dbus
+ExecStart=/usr/bin/env mapperx \
+ --service-namespaces="xyz. com. org." \
+ --interface-namespaces="org. com. xyz." \
+ --service-blacklists="org.freedesktop.systemd1"
+SyslogIdentifier=phosphor-mapper
+BusName={BUSNAME}
+TimeoutStartSec=300
+RestartSec=5
+EnvironmentFile={envfiledir}/obmc/mapper
+
+[Install]
+WantedBy={SYSTEMD_DEFAULT_TARGET}
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-mapper_%.bbappend b/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-mapper_%.bbappend
new file mode 100644
index 000000000..72d991c7e
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-mapper_%.bbappend
@@ -0,0 +1 @@
+FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/fans/phosphor-pid-control/phosphor-pid-control.service b/meta-openbmc-mods/meta-common/recipes-phosphor/fans/phosphor-pid-control/phosphor-pid-control.service
new file mode 100644
index 000000000..f4ffa17a0
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/fans/phosphor-pid-control/phosphor-pid-control.service
@@ -0,0 +1,12 @@
+[Unit]
+Description=Phosphor-Pid-Control Margin-based Fan Control Daemon
+
+[Service]
+Restart=always
+ExecStart={sbindir}/swampd
+RestartSec=5
+StartLimitInterval=0
+Type=simple
+
+[Install]
+WantedBy=basic.target
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/fans/phosphor-pid-control_%.bbappend b/meta-openbmc-mods/meta-common/recipes-phosphor/fans/phosphor-pid-control_%.bbappend
new file mode 100644
index 000000000..3ea7b96b1
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/fans/phosphor-pid-control_%.bbappend
@@ -0,0 +1,8 @@
+FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
+
+inherit obmc-phosphor-systemd
+SYSTEMD_SERVICE_${PN} = "phosphor-pid-control.service"
+EXTRA_OECONF = "--enable-configure-dbus=yes"
+
+SRC_URI = "git://github.com/openbmc/phosphor-pid-control.git"
+SRCREV = "f42741197ec807e0436a5e519ccff18519c67248"
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0001-image_verify-Add-support-for-OpenSSL-1.1.0.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0001-image_verify-Add-support-for-OpenSSL-1.1.0.patch
new file mode 100644
index 000000000..c5850473c
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0001-image_verify-Add-support-for-OpenSSL-1.1.0.patch
@@ -0,0 +1,130 @@
+From fa124c7944088624d40d6b265bac0651bd8235bb Mon Sep 17 00:00:00 2001
+From: Adriana Kobylak <anoo@us.ibm.com>
+Date: Thu, 6 Sep 2018 13:15:34 -0500
+Subject: [PATCH] image_verify: Add support for OpenSSL 1.1.0
+
+With OpenSSL 1.1.0, some of the functions were renamed, for
+example EVP_MD_CTX_create() and EVP_MD_CTX_destroy() were
+renamed to EVP_MD_CTX_new() and EVP_MD_CTX_free().
+Reference: https://wiki.openssl.org/index.php/OpenSSL_1.1.0_Changes
+Abstract them to support old and new APIs.
+
+Resolves openbmc/openbmc#3136
+
+Tested: Verified the signature verification was successful.
+
+Change-Id: I2297243fdd652055fe9ea88f26eb2dcf473d24e6
+Signed-off-by: Adriana Kobylak <anoo@us.ibm.com>
+
+%% original patch: 0001-image_verify-Add-support-for-OpenSSL-1.1.0.patch
+---
+ Makefile.am | 8 ++++++--
+ image_verify.cpp | 2 +-
+ image_verify.hpp | 1 +
+ utils.cpp | 29 +++++++++++++++++++++++++++++
+ utils.hpp | 15 +++++++++++++++
+ 5 files changed, 52 insertions(+), 3 deletions(-)
+ create mode 100644 utils.cpp
+ create mode 100644 utils.hpp
+
+diff --git a/Makefile.am b/Makefile.am
+index adba0e4..21b556f 100755
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -42,8 +42,12 @@ phosphor_image_updater_SOURCES = \
+ include ubi/Makefile.am.include
+
+ if WANT_SIGNATURE_VERIFY_BUILD
+-noinst_HEADERS += image_verify.hpp
+-phosphor_image_updater_SOURCES += image_verify.cpp
++noinst_HEADERS += \
++ image_verify.hpp \
++ utils.hpp
++phosphor_image_updater_SOURCES += \
++ image_verify.cpp \
++ utils.cpp
+ endif
+
+ if WANT_SYNC
+diff --git a/image_verify.cpp b/image_verify.cpp
+index 7d59910..ba6b24d 100644
+--- a/image_verify.cpp
++++ b/image_verify.cpp
+@@ -216,7 +216,7 @@ bool Signature::verifyFile(const fs::path& file, const fs::path& sigFile,
+ EVP_PKEY_assign_RSA(pKeyPtr.get(), publicRSA);
+
+ // Initializes a digest context.
+- EVP_MD_CTX_Ptr rsaVerifyCtx(EVP_MD_CTX_create(), ::EVP_MD_CTX_destroy);
++ EVP_MD_CTX_Ptr rsaVerifyCtx(EVP_MD_CTX_new(), ::EVP_MD_CTX_free);
+
+ // Adds all digest algorithms to the internal table
+ OpenSSL_add_all_digests();
+diff --git a/image_verify.hpp b/image_verify.hpp
+index cbd0e39..22ee5f9 100644
+--- a/image_verify.hpp
++++ b/image_verify.hpp
+@@ -1,4 +1,5 @@
+ #pragma once
++#include "utils.hpp"
+ #include <openssl/rsa.h>
+ #include <openssl/evp.h>
+ #include <openssl/pem.h>
+diff --git a/utils.cpp b/utils.cpp
+new file mode 100644
+index 0000000..95fc2e0
+--- /dev/null
++++ b/utils.cpp
+@@ -0,0 +1,29 @@
++#include "utils.hpp"
++
++#if OPENSSL_VERSION_NUMBER < 0x10100000L
++
++#include <string.h>
++
++static void* OPENSSL_zalloc(size_t num)
++{
++ void* ret = OPENSSL_malloc(num);
++
++ if (ret != NULL)
++ {
++ memset(ret, 0, num);
++ }
++ return ret;
++}
++
++EVP_MD_CTX* EVP_MD_CTX_new(void)
++{
++ return (EVP_MD_CTX*)OPENSSL_zalloc(sizeof(EVP_MD_CTX));
++}
++
++void EVP_MD_CTX_free(EVP_MD_CTX* ctx)
++{
++ EVP_MD_CTX_cleanup(ctx);
++ OPENSSL_free(ctx);
++}
++
++#endif // OPENSSL_VERSION_NUMBER < 0x10100000L
+diff --git a/utils.hpp b/utils.hpp
+new file mode 100644
+index 0000000..90569bf
+--- /dev/null
++++ b/utils.hpp
+@@ -0,0 +1,15 @@
++#pragma once
++
++// With OpenSSL 1.1.0, some functions were deprecated. Need to abstract them
++// to make the code backward compatible with older OpenSSL veresions.
++// Reference: https://wiki.openssl.org/index.php/OpenSSL_1.1.0_Changes
++#if OPENSSL_VERSION_NUMBER < 0x10100000L
++
++#include <openssl/evp.h>
++
++extern "C" {
++EVP_MD_CTX* EVP_MD_CTX_new(void);
++void EVP_MD_CTX_free(EVP_MD_CTX* ctx);
++}
++
++#endif // OPENSSL_VERSION_NUMBER < 0x10100000L
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/fwupd@.service b/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/fwupd@.service
new file mode 100644
index 000000000..d51fee312
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/fwupd@.service
@@ -0,0 +1,8 @@
+[Unit]
+Description=Flash BMC with fwupd script : %I
+
+[Service]
+Type=oneshot
+RemainAfterExit=no
+ExecStart=/usr/bin/fwupd.sh file:////tmp/images/%i/image-runtime
+SyslogIdentifier=fwupd \ No newline at end of file
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager_%.bbappend b/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager_%.bbappend
new file mode 100644
index 000000000..9c3c3ee37
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager_%.bbappend
@@ -0,0 +1,11 @@
+FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
+EXTRA_OECONF += "--enable-fwupd_script"
+
+SYSTEMD_SERVICE_${PN}-updater += "fwupd@.service"
+
+SRC_URI_remove = "git://github.com/openbmc/phosphor-bmc-code-mgmt"
+SRC_URI += "git://git-amr-2.devtools.intel.com:29418/openbmc-phosphor-bmc-code-mgmt;protocol=ssh"
+SRCREV = "f8f76c29dbe2806a6eacd15847563cdf7f7567f4"
+
+#Currently enforcing image signature validation only for PFR images
+PACKAGECONFIG_append = "${@bb.utils.contains('IMAGE_TYPE', 'pfr', ' verify_signature', '', d)}"
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/gpiodaemon/gpiodaemon.bb b/meta-openbmc-mods/meta-common/recipes-phosphor/gpiodaemon/gpiodaemon.bb
new file mode 100644
index 000000000..6d6762fc9
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/gpiodaemon/gpiodaemon.bb
@@ -0,0 +1,18 @@
+SUMMARY = "Gpio daemon service for handling gpio operations"
+DESCRIPTION = "Daemon allows to block gpio access under certain conditions"
+
+PV = "1.0+git${SRCPV}"
+
+S = "${WORKDIR}/git/gpiodaemon"
+
+LICENSE = "Apache-2.0"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=e3fc50a88d0a364313df4b21ef20c29e"
+
+SRC_URI = "git://git@github.com/Intel-BMC/provingground.git;protocol=ssh"
+
+SRCREV = "3cc86d6c536b4c5ee7afb5447837b83ce8b3d149"
+
+inherit cmake systemd
+SYSTEMD_SERVICE_${PN} = "gpiodaemon.service"
+
+DEPENDS = "boost systemd sdbusplus phosphor-logging"
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/host/obmc-op-control-host%.bbappend b/meta-openbmc-mods/meta-common/recipes-phosphor/host/obmc-op-control-host%.bbappend
new file mode 100644
index 000000000..5326680f6
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/host/obmc-op-control-host%.bbappend
@@ -0,0 +1,6 @@
+SYSTEMD_LINK_${PN}_remove += "../op-start-host@.service:obmc-host-startmin@0.target.requires/op-start-host@0.service"
+SYSTEMD_LINK_${PN}_remove += "../op-init-pnor@.service:obmc-host-startmin@0.target.requires/op-init-pnor@0.service"
+
+FILES_${PN}_remove = "${systemd_unitdir}/system/obmc-host-startmin@0.target.requires"
+FILES_${PN}_remove = "${systemd_unitdir}/system/obmc-host-startmin@0.target.requires/op-start-host@0.service"
+FILES_${PN}_remove = "${systemd_unitdir}/system/obmc-host-startmin@0.target.requires/op-init-pnor@0.service" \ No newline at end of file
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/bmcweb.socket b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/bmcweb.socket
new file mode 100644
index 000000000..8782e4dd3
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/bmcweb.socket
@@ -0,0 +1,9 @@
+[Unit]
+Description=BMC Webserver socket
+
+[Socket]
+ListenStream=443
+ReusePort=true
+
+[Install]
+WantedBy=sockets.target
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb_%.bbappend b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb_%.bbappend
new file mode 100644
index 000000000..72d991c7e
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb_%.bbappend
@@ -0,0 +1 @@
+FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-channel-inventory%.bbappend b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-channel-inventory%.bbappend
new file mode 100644
index 000000000..d79704ec6
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-channel-inventory%.bbappend
@@ -0,0 +1,4 @@
+FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
+
+SRC_URI += " file://channel.yaml \
+ "
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-channel-inventory%/channel.yaml b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-channel-inventory%/channel.yaml
new file mode 100644
index 000000000..032e05127
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-channel-inventory%/channel.yaml
@@ -0,0 +1,8 @@
+# Channel Number (must be unique) is the key
+1:
+ # ifName the ethernet device name (used in the dbus path)
+ ifName: eth0
+2:
+ ifName: eth1
+3:
+ ifName: eth1
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..13b945fd0
--- /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" : "eth2",
+ "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
+ }
+ },
+ "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" : "EMP",
+ "is_valid" : true,
+ "active_sessions" : 0,
+ "channel_info" : {
+ "medium_type" : "ipmb",
+ "protocol_type" : "ipmb-1.0",
+ "session_supported" : "session-less",
+ "is_ipmi" : true
+ }
+ },
+ "5" : {
+ "name" : "ICMB",
+ "is_valid" : false,
+ "active_sessions" : 0,
+ "channel_info" : {
+ "medium_type" : "ipmb",
+ "protocol_type" : "ipmb-1.0",
+ "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" : "SMM",
+ "is_valid" : true,
+ "active_sessions" : 0,
+ "channel_info" : {
+ "medium_type" : "ipmb",
+ "protocol_type" : "ipmb-1.0",
+ "session_supported" : "session-less",
+ "is_ipmi" : true
+ }
+ },
+ "8" : {
+ "name" : "INTRABMC",
+ "is_valid" : true,
+ "active_sessions" : 0,
+ "channel_info" : {
+ "medium_type" : "ipmb",
+ "protocol_type" : "ipmb-1.0",
+ "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" : "ipmb",
+ "protocol_type" : "ipmb-1.0",
+ "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" : "ipmb",
+ "protocol_type" : "ipmb-1.0",
+ "session_supported" : "session-less",
+ "is_ipmi" : true
+ }
+ },
+ "14" : {
+ "name" : "SELF",
+ "is_valid" : false,
+ "active_sessions" : 0,
+ "channel_info" : {
+ "medium_type" : "ipmb",
+ "protocol_type" : "ipmb-1.0",
+ "session_supported" : "session-less",
+ "is_ipmi" : true
+ }
+ },
+ "15" : {
+ "name" : "SMS",
+ "is_valid" : true,
+ "active_sessions" : 0,
+ "channel_info" : {
+ "medium_type" : "ipmb",
+ "protocol_type" : "ipmb-1.0",
+ "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..9fdb3c916
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-config/master_write_read_white_list.json
@@ -0,0 +1,49 @@
+{
+ "filters": [
+ {
+ "busId": "0x01",
+ "slaveAddr": "0x4d",
+ "command": "0x00"
+ },
+ {
+ "busId": "0x01",
+ "slaveAddr": "0x57",
+ "command": "0x00"
+ },
+ {
+ "busId": "0x02",
+ "slaveAddr": "0x40",
+ "command": "0x00"
+ },
+ {
+ "busId": "0x02",
+ "slaveAddr": "0x49",
+ "command": "0x00"
+ },
+ {
+ "busId": "0x02",
+ "slaveAddr": "0x51",
+ "command": "0x00"
+ },
+ {
+ "busId": "0x03",
+ "slaveAddr": "0x44",
+ "command": "0x00"
+ },
+ {
+ "busId": "0x03",
+ "slaveAddr": "0x68",
+ "command": "0x00"
+ },
+ {
+ "busId": "0x06",
+ "slaveAddr": "0x40",
+ "command": "0x00"
+ },
+ {
+ "busId": "0x07",
+ "slaveAddr": "0x51",
+ "command": "0x00"
+ }
+ ]
+}
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/0002-Modify-dbus-interface-for-power-control.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0002-Modify-dbus-interface-for-power-control.patch
new file mode 100644
index 000000000..236bd18f4
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0002-Modify-dbus-interface-for-power-control.patch
@@ -0,0 +1,31 @@
+From 39df500f277eca01d6a0538d4db8ec34894d9441 Mon Sep 17 00:00:00 2001
+From: Yong Li <yong.b.li@linux.intel.com>
+Date: Mon, 17 Sep 2018 12:59:12 +0800
+Subject: [PATCH] Modify dbus interface for power control
+
+Switch power control service namespace from "org" to "xyz",
+to compatible with new intel-chassis services
+
+Signed-off-by: Yong Li <yong.b.li@linux.intel.com>
+---
+ chassishandler.cpp | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/chassishandler.cpp b/chassishandler.cpp
+index 6002e7a..0e83bba 100644
+--- a/chassishandler.cpp
++++ b/chassishandler.cpp
+@@ -786,8 +786,8 @@ ipmi_ret_t ipmi_get_chassis_status(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+ ipmi_data_len_t data_len,
+ ipmi_context_t context)
+ {
+- const char* objname = "/org/openbmc/control/power0";
+- const char* intf = "org.openbmc.control.Power";
++ const char* objname = "/xyz/openbmc_project/Chassis/Control/Power0";
++ const char* intf = "xyz.openbmc_project.Chassis.Control.Power";
+
+ sd_bus* bus = NULL;
+ sd_bus_message* reply = NULL;
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0003-Modify-dbus-interface-for-chassis-control.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0003-Modify-dbus-interface-for-chassis-control.patch
new file mode 100644
index 000000000..9061481ac
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0003-Modify-dbus-interface-for-chassis-control.patch
@@ -0,0 +1,33 @@
+From 48ac37551cd51415deafe8b1dcb23ebeef1e8ade Mon Sep 17 00:00:00 2001
+From: Yong Li <yong.b.li@linux.intel.com>
+Date: Mon, 17 Sep 2018 13:04:42 +0800
+Subject: [PATCH] Modify-dbus-interface-for-chassis-control
+
+Switch chassis control service namespace from "org" to "xyz",
+to compatible with new intel-chassis services
+
+Signed-off-by: Kuiying Wang <kuiying.wang@intel.com>
+Signed-off-by: Yong Li <yong.b.li@linux.intel.com>
+---
+ apphandler.cpp | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/apphandler.cpp b/apphandler.cpp
+index b089331..f2889c5 100644
+--- a/apphandler.cpp
++++ b/apphandler.cpp
+@@ -393,9 +393,9 @@ ipmi_ret_t ipmi_app_get_device_guid(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+ ipmi_data_len_t data_len,
+ ipmi_context_t context)
+ {
+- const char* objname = "/org/openbmc/control/chassis0";
++ const char* objname = "/xyz/openbmc_project/Chassis/Control/Chassis";
+ const char* iface = "org.freedesktop.DBus.Properties";
+- const char* chassis_iface = "org.openbmc.control.Chassis";
++ const char* chassis_iface = "xyz.openbmc_project.Chassis.Control.Chassis";
+ sd_bus_message* reply = NULL;
+ sd_bus_error error = SD_BUS_ERROR_NULL;
+ int r = 0;
+--
+2.7.4
+
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..3d9179ce5
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0009-IPv6-Network-changes.patch
@@ -0,0 +1,909 @@
+From cd4bc9e4291771f638f66efa205bf8fbec518546 Mon Sep 17 00:00:00 2001
+From: Vernon Mauery <vernon.mauery@linux.intel.com>
+Date: Mon, 4 Feb 2019 10:30:12 -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
+---
+ transporthandler.cpp | 667 ++++++++++++++++++++++++++++++++++++++++++-
+ transporthandler.hpp | 68 +++++
+ types.hpp | 9 +
+ utils.hpp | 1 +
+ 4 files changed, 744 insertions(+), 1 deletion(-)
+
+Index: phosphor-host-ipmid.clean/transporthandler.cpp
+===================================================================
+--- phosphor-host-ipmid.clean.orig/transporthandler.cpp
++++ phosphor-host-ipmid.clean/transporthandler.cpp
+@@ -41,6 +41,12 @@ extern std::unique_ptr<phosphor::Timer>
+
+ 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;
+
+@@ -400,7 +406,6 @@ ipmi_ret_t ipmi_transport_set_lan(ipmi_n
+ ipmi_context_t context)
+ {
+ ipmi_ret_t rc = IPMI_CC_OK;
+- *data_len = 0;
+
+ using namespace std::chrono_literals;
+
+@@ -414,6 +419,9 @@ ipmi_ret_t ipmi_transport_set_lan(ipmi_n
+ auto reqptr = reinterpret_cast<const set_lan_t*>(request);
+ sdbusplus::bus::bus bus(ipmid_get_sd_bus_connection());
+
++ size_t reqLen = *data_len;
++ *data_len = 0;
++
+ // channel number is the lower nibble
+ int channel = reqptr->channel & CHANNEL_MASK;
+ auto ethdevice = ipmi::network::ChanneltoEthernet(channel);
+@@ -437,6 +445,11 @@ ipmi_ret_t ipmi_transport_set_lan(ipmi_n
+
+ case LanParam::IPSRC:
+ {
++ if (reqLen != LAN_PARAM_IPSRC_SIZE)
++ {
++ 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);
+@@ -445,6 +458,11 @@ ipmi_ret_t ipmi_transport_set_lan(ipmi_n
+
+ case LanParam::MAC:
+ {
++ if (reqLen != LAN_PARAM_MAC_SIZE)
++ {
++ return IPMI_CC_REQ_DATA_LEN_INVALID;
++ }
++
+ char mac[SIZE_MAC];
+
+ std::snprintf(mac, SIZE_MAC, ipmi::network::MAC_ADDRESS_FORMAT,
+@@ -465,6 +483,11 @@ ipmi_ret_t ipmi_transport_set_lan(ipmi_n
+
+ case LanParam::SUBNET:
+ {
++ if (reqLen != LAN_PARAM_SUBNET_SIZE)
++ {
++ 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]);
+@@ -474,6 +497,11 @@ ipmi_ret_t ipmi_transport_set_lan(ipmi_n
+
+ case LanParam::GATEWAY:
+ {
++ if (reqLen != LAN_PARAM_GATEWAY_SIZE)
++ {
++ 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]);
+@@ -483,6 +511,11 @@ ipmi_ret_t ipmi_transport_set_lan(ipmi_n
+
+ case LanParam::VLAN:
+ {
++ if (reqLen != LAN_PARAM_VLAN_SIZE)
++ {
++ return IPMI_CC_REQ_DATA_LEN_INVALID;
++ }
++
+ uint16_t vlan{};
+ std::memcpy(&vlan, reqptr->data, ipmi::network::VLAN_SIZE_BYTE);
+ // We are not storing the enable bit
+@@ -495,6 +528,11 @@ ipmi_ret_t ipmi_transport_set_lan(ipmi_n
+
+ case LanParam::INPROGRESS:
+ {
++ if (reqLen != LAN_PARAM_INPROGRESS_SIZE)
++ {
++ return IPMI_CC_REQ_DATA_LEN_INVALID;
++ }
++
+ if (reqptr->data[0] == SET_COMPLETE)
+ {
+ channelConf->lan_set_in_progress = SET_COMPLETE;
+@@ -523,6 +561,122 @@ ipmi_ret_t ipmi_transport_set_lan(ipmi_n
+ }
+ break;
+
++ case LanParam::IPV6_AND_IPV4_ENABLES:
++ {
++ if (reqLen != LAN_PARAM_IPV6_AND_IPV4_ENABLES_SIZE)
++ {
++ return IPMI_CC_REQ_DATA_LEN_INVALID;
++ }
++
++ channelConf->ipv6AddressingEnables = reqptr->data[0];
++ break;
++ }
++
++ case LanParam::IPV6_STATIC_ADDRESSES:
++ {
++ if (reqLen != LAN_PARAM_IPV6_STATIC_ADDRESSES_SIZE)
++ {
++ 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 != LAN_PARAM_IPV6_ROUTER_ADDRESS_CONF_CTRL_SIZE)
++ {
++ return IPMI_CC_REQ_DATA_LEN_INVALID;
++ }
++
++ channelConf->ipv6RouterAddressConfigControl = reqptr->data[0];
++ break;
++ }
++
++ case LanParam::IPV6_STATIC_ROUTER_1_IP_ADDR:
++ {
++ if (reqLen != LAN_PARAM_IPV6_STATIC_ROUTER_1_IP_ADDR_SIZE)
++ {
++ 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 != LAN_PARAM_IPV6_STATIC_ROUTER_1_PREFIX_LEN_SIZE)
++ {
++ return IPMI_CC_REQ_DATA_LEN_INVALID;
++ }
++
++ channelConf->ipv6GatewayPrefixLength = reqptr->data[0];
++ break;
++ }
++
++ case LanParam::IPV6_STATIC_ROUTER_1_PREFIX_VAL:
++ {
++ if (reqLen != LAN_PARAM_IPV6_STATIC_ROUTER_1_PREFIX_VAL_SIZE)
++ {
++ 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 != LAN_PARAM_IPV6_STATIC_ROUTER_2_IP_ADDR_SIZE)
++ {
++ 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 != LAN_PARAM_IPV6_STATIC_ROUTER_2_PREFIX_LEN_SIZE)
++ {
++ return IPMI_CC_REQ_DATA_LEN_INVALID;
++ }
++
++ channelConf->ipv6BackupGatewayPrefixLength = reqptr->data[0];
++ break;
++ }
++
++ case LanParam::IPV6_STATIC_ROUTER_2_PREFIX_VAL:
++ {
++ if (reqLen != LAN_PARAM_IPV6_STATIC_ROUTER_2_PREFIX_VAL_SIZE)
++ {
++ 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;
+@@ -549,6 +703,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
+@@ -687,6 +842,489 @@ 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;
++ }
++
++ std::string ipEnables =
++ sdbusplus::message::variant_ns::get<std::string>(
++ ipmi::getDbusProperty(bus, ipmi::network::SERVICE,
++ networkInterfacePath,
++ ipmi::network::ETHERNET_INTERFACE,
++ "IPAddressEnables"));
++
++ // 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);
++
++ std::string origin =
++ sdbusplus::message::variant_ns::get<std::string>(
++ properties["Origin"]);
++ if (sdbusplus::message::variant_ns::get<std::string>(
++ properties["Origin"]) ==
++ "xyz.openbmc_project.Network.IP.AddressOrigin.Static")
++ {
++ ipaddress =
++ sdbusplus::message::variant_ns::get<std::string>(
++ properties["Address"]);
++ ipv6AddressSource = 0x81; // Looking at bit 0 and bit 7
++ prefixLength =
++ sdbusplus::message::variant_ns::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 =
++ sdbusplus::message::variant_ns::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 (sdbusplus::message::variant_ns::get<std::string>(
++ properties["Origin"]) ==
++ "xyz.openbmc_project.Network.IP.AddressOrigin.DHCP")
++ {
++ ipaddress =
++ sdbusplus::message::variant_ns::get<std::string>(
++ properties["Address"]);
++ ipv6AddressSource = 0x81; // Looking at bit 0 and bit 7
++ prefixLength =
++ sdbusplus::message::variant_ns::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 =
++ sdbusplus::message::variant_ns::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 = sdbusplus::message::variant_ns::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));
+@@ -932,6 +1570,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,
+@@ -939,7 +1587,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 (InternalFailure& e)
+ {
+Index: phosphor-host-ipmid.clean/transporthandler.hpp
+===================================================================
+--- phosphor-host-ipmid.clean.orig/transporthandler.hpp
++++ phosphor-host-ipmid.clean/transporthandler.hpp
+@@ -80,6 +80,28 @@ enum class LanParam : uint8_t
+ IPV6_NEIGHBOR_TIMING_CONFIGURATION = 80,
+ };
+
++// Data length of parameters
++constexpr size_t LAN_PARAM_INPROGRESS_SIZE = 3;
++constexpr size_t LAN_PARAM_IP_SIZE = 6;
++constexpr size_t LAN_PARAM_IPSRC_SIZE = 3;
++constexpr size_t LAN_PARAM_MAC_SIZE = 8;
++constexpr size_t LAN_PARAM_SUBNET_SIZE = 6;
++constexpr size_t LAN_PARAM_GATEWAY_SIZE = 6;
++constexpr size_t LAN_PARAM_VLAN_SIZE = 4;
++constexpr size_t LAN_PARAM_IPV6_AND_IPV4_ENABLES_SIZE = 3;
++constexpr size_t LAN_PARAM_IPV6_STATIC_ADDRESSES_SIZE = 23;
++constexpr size_t LAN_PARAM_IPV6_ROUTER_ADDRESS_CONF_CTRL_SIZE = 3;
++constexpr size_t LAN_PARAM_IPV6_STATIC_ROUTER_1_IP_ADDR_SIZE = 18;
++constexpr size_t LAN_PARAM_IPV6_STATIC_ROUTER_1_PREFIX_LEN_SIZE = 3;
++constexpr size_t LAN_PARAM_IPV6_STATIC_ROUTER_1_PREFIX_VAL_SIZE = 19;
++constexpr size_t LAN_PARAM_IPV6_STATIC_ROUTER_2_IP_ADDR_SIZE = 18;
++constexpr size_t LAN_PARAM_IPV6_STATIC_ROUTER_2_PREFIX_LEN_SIZE = 3;
++constexpr size_t LAN_PARAM_IPV6_STATIC_ROUTER_2_PREFIX_VAL_SIZE = 19;
++
++constexpr uint8_t DUID_LEN = 10;
++constexpr uint8_t DUID_LL_TYPE = 3;
++constexpr uint8_t DUIC_ETH_HW_TYPE = 1;
++
+ constexpr uint8_t SET_COMPLETE = 0;
+ constexpr uint8_t SET_IN_PROGRESS = 1;
+ constexpr uint8_t SET_COMMIT_WRITE = 2; // Optional
+@@ -102,6 +124,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();
+@@ -112,6 +148,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();
+ }
+ };
+
+Index: phosphor-host-ipmid.clean/types.hpp
+===================================================================
+--- phosphor-host-ipmid.clean.orig/types.hpp
++++ phosphor-host-ipmid.clean/types.hpp
+@@ -209,6 +209,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";
+@@ -220,6 +221,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
+ {
+@@ -228,5 +230,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/utils.hpp
+===================================================================
+--- phosphor-host-ipmid.clean.orig/utils.hpp
++++ phosphor-host-ipmid.clean/utils.hpp
+@@ -246,6 +246,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";
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..c1ec6ac6e
--- /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,56 @@
+From 4953a9f2233fd24a28da84443cea6aebecd14fbc Mon Sep 17 00:00:00 2001
+From: Yong Li <yong.b.li@linux.intel.com>
+Date: Mon, 17 Sep 2018 13:20:54 +0800
+Subject: [PATCH] fix "get system GUID" ipmi command
+
+Change-Id: I15c71607c24ad8b3e2c9065a5470002ecb1761bb
+Signed-off-by: Jia, Chunhui <chunhui.jia@intel.com>
+Signed-off-by: Yong Li <yong.b.li@linux.intel.com>
+---
+ apphandler.cpp | 7 ++-----
+ host-ipmid-whitelist.conf | 1 +
+ 2 files changed, 3 insertions(+), 5 deletions(-)
+
+diff --git a/apphandler.cpp b/apphandler.cpp
+index f2889c5..9149373 100644
+--- a/apphandler.cpp
++++ b/apphandler.cpp
+@@ -48,7 +48,7 @@ extern sd_bus* bus;
+
+ constexpr auto bmc_state_interface = "xyz.openbmc_project.State.BMC";
+ constexpr auto bmc_state_property = "CurrentBMCState";
+-constexpr auto bmc_interface = "xyz.openbmc_project.Inventory.Item.Bmc";
++// phosphor-setting-manager is the unique service that holds this interface
+ constexpr auto bmc_guid_interface = "xyz.openbmc_project.Common.UUID";
+ constexpr auto bmc_guid_property = "UUID";
+ constexpr auto bmc_guid_len = 16;
+@@ -546,8 +545,7 @@ ipmi_ret_t ipmi_app_get_sys_guid(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+ {
+ // Get the Inventory object implementing BMC interface
+ ipmi::DbusObjectInfo bmcObject =
+- ipmi::getDbusObject(bus, bmc_interface);
+-
++ ipmi::getDbusObject(bus, bmc_guid_interface);
+ // Read UUID property value from bmcObject
+ // UUID is in RFC4122 format Ex: 61a39523-78f2-11e5-9862-e6402cfc3223
+ auto variant =
+@@ -591,7 +589,6 @@ ipmi_ret_t ipmi_app_get_sys_guid(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+ catch (const InternalFailure& e)
+ {
+ log<level::ERR>("Failed in reading BMC UUID property",
+- entry("INTERFACE=%s", bmc_interface),
+ entry("PROPERTY_INTERFACE=%s", bmc_guid_interface),
+ entry("PROPERTY=%s", bmc_guid_property));
+ return IPMI_CC_UNSPECIFIED_ERROR;
+diff --git a/host-ipmid-whitelist.conf b/host-ipmid-whitelist.conf
+index 2c37ac9..164edbe 100644
+--- a/host-ipmid-whitelist.conf
++++ b/host-ipmid-whitelist.conf
+@@ -40,3 +40,4 @@
+ 0x2C:0x06 //<Group Extension>:<Get Asset Tag>
+ 0x2C:0x07 //<Group Extension>:<Get Sensor Info>
+ 0x2C:0x10 //<Group Extension>:<Get Temperature Readings>
++0x30:0x41 //<OEM>:<Set System GUID>
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0012-ipmi-set-get-boot-options.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0012-ipmi-set-get-boot-options.patch
new file mode 100644
index 000000000..243015c95
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0012-ipmi-set-get-boot-options.patch
@@ -0,0 +1,64 @@
+From 7b5c6a54c049a447b1fd3a42f9d63322dcee4dc7 Mon Sep 17 00:00:00 2001
+From: Yong Li <yong.b.li@linux.intel.com>
+Date: Sun, 16 Sep 2018 19:45:10 +0800
+Subject: [PATCH] [ipmi] set/get boot options
+
+1. fix issue for handling unsupported paramter
+2. add support for floppy/USB boot
+
+Change-Id: I2b888c1ad67fec7924dd5825f78622cd216a55f4
+Signed-off-by: Jia, Chunhui <chunhui.jia@intel.com>
+Signed-off-by: Yong Li <yong.b.li@linux.intel.com>
+---
+ chassishandler.cpp | 14 +++++++++++---
+ 1 file changed, 11 insertions(+), 3 deletions(-)
+
+diff --git a/chassishandler.cpp b/chassishandler.cpp
+index 666addb..77af2dc 100644
+--- a/chassishandler.cpp
++++ b/chassishandler.cpp
+@@ -1244,7 +1244,8 @@ constexpr auto ipmiDefault = 0;
+ std::map<IpmiValue, Source::Sources> sourceIpmiToDbus = {
+ {0x01, Source::Sources::Network},
+ {0x02, Source::Sources::Disk},
+- {0x05, Source::Sources::ExternalMedia},
++ {0x05, Source::Sources::DVD},
++ {0x0f, Source::Sources::Removable},
+ {ipmiDefault, Source::Sources::Default}};
+
+ std::map<IpmiValue, Mode::Modes> modeIpmiToDbus = {
+@@ -1255,7 +1256,8 @@ std::map<IpmiValue, Mode::Modes> modeIpmiToDbus = {
+ std::map<Source::Sources, IpmiValue> sourceDbusToIpmi = {
+ {Source::Sources::Network, 0x01},
+ {Source::Sources::Disk, 0x02},
+- {Source::Sources::ExternalMedia, 0x05},
++ {Source::Sources::DVD, 0x05},
++ {Source::Sources::Removable, 0x0f},
+ {Source::Sources::Default, ipmiDefault}};
+
+ std::map<Mode::Modes, IpmiValue> modeDbusToIpmi = {
+@@ -1533,7 +1535,7 @@ ipmi_ret_t ipmi_chassis_set_sys_boot_options(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+ setBootMode(Mode::Modes::Regular);
+ }
+ }
+- if (modeIpmiToDbus.end() != modeItr)
++ else if (modeIpmiToDbus.end() != modeItr)
+ {
+ rc = setBootMode(modeItr->second);
+ if (rc != IPMI_CC_OK)
+@@ -1550,6 +1552,12 @@ ipmi_ret_t ipmi_chassis_set_sys_boot_options(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+ setBootSource(Source::Sources::Default);
+ }
+ }
++ else
++ {
++ // if boot option is not in support list, return error
++ *data_len = 0;
++ return IPMI_CC_INVALID_FIELD_REQUEST;
++ }
+ }
+ catch (InternalFailure& e)
+ {
+--
+2.7.4
+
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..ae10ab60a
--- /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,25 @@
+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(+)
+
+diff --git a/host-ipmid-whitelist.conf b/host-ipmid-whitelist.conf
+index 164edbe..db54a49 100644
+--- a/host-ipmid-whitelist.conf
++++ b/host-ipmid-whitelist.conf
+@@ -41,3 +41,5 @@
+ 0x2C:0x07 //<Group Extension>:<Get Sensor Info>
+ 0x2C:0x10 //<Group Extension>:<Get Temperature Readings>
+ 0x30:0x41 //<OEM>:<Set System GUID>
++0x30:0x26 //<OEM>:<Set BIOS ID>
++0x30:0x27 //<OEM>:<Get Device Info>
+--
+2.16.2
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0014-Enable-get-device-guid-ipmi-command.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0014-Enable-get-device-guid-ipmi-command.patch
new file mode 100644
index 000000000..46dd99466
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0014-Enable-get-device-guid-ipmi-command.patch
@@ -0,0 +1,45 @@
+From 482a6cc52d0ec514d6da5f4bcb04b4991f3cc36e Mon Sep 17 00:00:00 2001
+From: Yong Li <yong.b.li@linux.intel.com>
+Date: Mon, 17 Sep 2018 13:41:25 +0800
+Subject: [PATCH] Enable get device guid ipmi command
+
+The UUID interface is changed, modify the API to get the correct UUID
+for device guid
+
+Change-Id: I0c0c7bd350992ac03f928707986a7180407d8f3f
+Signed-off-by: Yong Li <yong.b.li@linux.intel.com>
+---
+ apphandler.cpp | 8 +++++---
+ 1 file changed, 5 insertions(+), 3 deletions(-)
+
+diff --git a/apphandler.cpp b/apphandler.cpp
+index 937be71..89d797a 100644
+--- a/apphandler.cpp
++++ b/apphandler.cpp
+@@ -392,9 +392,10 @@ ipmi_ret_t ipmi_app_get_device_guid(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+ ipmi_data_len_t data_len,
+ ipmi_context_t context)
+ {
+- const char* objname = "/xyz/openbmc_project/Chassis/Control/Chassis";
++ const char* objname =
++ "/xyz/openbmc_project/inventory/system/chassis/motherboard/bmc";
+ const char* iface = "org.freedesktop.DBus.Properties";
+- const char* chassis_iface = "xyz.openbmc_project.Chassis.Control.Chassis";
++ const char* uuid_iface = "xyz.openbmc_project.Common.UUID";
+ sd_bus_message* reply = NULL;
+ sd_bus_error error = SD_BUS_ERROR_NULL;
+ int r = 0;
+@@ -426,8 +427,9 @@ ipmi_ret_t ipmi_app_get_device_guid(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+ entry("ERRNO=0x%X", -r));
+ goto finish;
+ }
++
+ r = sd_bus_call_method(bus, busname, objname, iface, "Get", &error, &reply,
+- "ss", chassis_iface, "uuid");
++ "ss", uuid_iface, "UUID");
+ if (r < 0)
+ {
+ log<level::ERR>("Failed to call Get Method", entry("ERRNO=0x%X", -r));
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0016-add-better-sdbusplus-exception-handling.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0016-add-better-sdbusplus-exception-handling.patch
new file mode 100644
index 000000000..873eb6b16
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0016-add-better-sdbusplus-exception-handling.patch
@@ -0,0 +1,153 @@
+From a445f287d4aebca68dc0321e292933311caf59ba Mon Sep 17 00:00:00 2001
+From: Yong Li <yong.b.li@linux.intel.com>
+Date: Sun, 16 Sep 2018 20:14:55 +0800
+Subject: [PATCH] add better sdbusplus exception handling
+
+Now that sdbusplus throws, we need to catch more stuff. To compound the
+problem, even though sdbusplus::exception::exception inherits from
+std::exception, there is a problem that prevents the code from simply
+catching std::exception.
+
+Change-Id: I2a330e542f5d87722a4c04e6d47de2cfb2f7d7c9
+Signed-off-by: Vernon Mauery <vernon.mauery@intel.com>
+Signed-off-by: Yong Li <yong.b.li@linux.intel.com>
+
+---
+ apphandler.cpp | 14 +++++++--
+ ipmid.cpp | 77 +++++++++++++++++++++++++++++++++++---------------
+ 2 files changed, 66 insertions(+), 25 deletions(-)
+
+diff --git a/apphandler.cpp b/apphandler.cpp
+index 126de33..3cae6d5 100644
+--- a/apphandler.cpp
++++ b/apphandler.cpp
+@@ -312,9 +312,19 @@ ipmi_ret_t ipmi_app_get_device_id(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+ auto version = getActiveSoftwareVersionInfo();
+ r = convert_version(version.c_str(), &rev);
+ }
+- catch (const std::exception& e)
++ catch (sdbusplus::exception::exception& e)
+ {
+- log<level::ERR>(e.what());
++ log<level::ERR>("sdbusplus::exception",
++ entry("ERROR=%s", e.what()));
++ }
++ catch (std::exception& e)
++ {
++ log<level::ERR>("unexpected exception",
++ entry("ERROR=%s", e.what()));
++ }
++ catch (...)
++ {
++ log<level::ERR>("unknown exception");
+ }
+
+ if (r >= 0)
+diff --git a/ipmid.cpp b/ipmid.cpp
+index 2d48bfe..8d2fb37 100644
+--- a/ipmid.cpp
++++ b/ipmid.cpp
+@@ -273,6 +273,10 @@ ipmi_ret_t ipmi_netfn_router(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+ }
+ // IPMI command handlers can throw unhandled exceptions, catch those
+ // and return sane error code.
++ catch (sdbusplus::exception::exception& e)
++ {
++ log<level::ERR>("sdbusplus exception", entry("EXCEPTION=%s", e.what()));
++ }
+ catch (const std::exception& e)
+ {
+ log<level::ERR>(e.what(), entry("NET_FUN=0x%X", netfn),
+@@ -281,6 +285,23 @@ ipmi_ret_t ipmi_netfn_router(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+ *data_len = 0;
+ // fall through
+ }
++ catch (...)
++ {
++ std::exception_ptr eptr = std::current_exception();
++ try
++ {
++ std::rethrow_exception(eptr);
++ }
++ catch (std::exception& e)
++ {
++ log<level::ERR>("unexpected uncaught exception",
++ entry("EXCEPTION=%s", e.what()),
++ entry("NET_FUN=0x%X", netfn),
++ entry("CMD=0x%X", cmd));
++ rc = IPMI_CC_UNSPECIFIED_ERROR;
++ *data_len = 0;
++ }
++ }
+ // Now copy the return code that we got from handler and pack it in first
+ // byte.
+ std::memcpy(response, &rc, IPMI_CC_LEN);
+@@ -361,32 +382,42 @@ final:
+ void cache_restricted_mode()
+ {
+ restricted_mode = false;
+- using namespace sdbusplus::xyz::openbmc_project::Control::Security::server;
+- using namespace internal;
+- using namespace internal::cache;
+- sdbusplus::bus::bus dbus(ipmid_get_sd_bus_connection());
+- const auto& restrictionModeSetting =
+- objects->map.at(restrictionModeIntf).front();
+- auto method = dbus.new_method_call(
+- objects->service(restrictionModeSetting, restrictionModeIntf).c_str(),
+- restrictionModeSetting.c_str(), "org.freedesktop.DBus.Properties",
+- "Get");
+- method.append(restrictionModeIntf, "RestrictionMode");
+- auto resp = dbus.call(method);
+- if (resp.is_method_error())
++ try
+ {
+- log<level::ERR>("Error in RestrictionMode Get");
+- // Fail-safe to true.
+- restricted_mode = true;
+- return;
++ using namespace sdbusplus::xyz::openbmc_project::Control::Security::
++ server;
++ using namespace internal;
++ using namespace internal::cache;
++ sdbusplus::bus::bus dbus(ipmid_get_sd_bus_connection());
++ const auto& restrictionModeSetting =
++ objects->map.at(restrictionModeIntf).front();
++ auto method = dbus.new_method_call(
++ objects->service(restrictionModeSetting, restrictionModeIntf)
++ .c_str(),
++ restrictionModeSetting.c_str(), "org.freedesktop.DBus.Properties",
++ "Get");
++ method.append(restrictionModeIntf, "RestrictionMode");
++ auto resp = dbus.call(method);
++ if (resp.is_method_error())
++ {
++ log<level::ERR>("Error in RestrictionMode Get");
++ // Fail-safe to true.
++ restricted_mode = true;
++ return;
++ }
++ sdbusplus::message::variant<std::string> result;
++ resp.read(result);
++ auto restrictionMode = RestrictionMode::convertModesFromString(
++ sdbusplus::message::variant_ns::get<std::string>(result));
++ if (RestrictionMode::Modes::Whitelist == restrictionMode)
++ {
++ restricted_mode = true;
++ }
+ }
+- sdbusplus::message::variant<std::string> result;
+- resp.read(result);
+- auto restrictionMode = RestrictionMode::convertModesFromString(
+- variant_ns::get<std::string>(result));
+- if (RestrictionMode::Modes::Whitelist == restrictionMode)
++ catch (sdbusplus::exception::exception& e)
+ {
+- restricted_mode = true;
++ // restrictionModeIntf does not exist; default to not enforcing
++ log<level::ERR>("sdbusplus exception", entry("EXCEPTION=%s", e.what()));
+ }
+ }
+
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0018-Catch-sdbusplus-exceptions-in-IPMI-net.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0018-Catch-sdbusplus-exceptions-in-IPMI-net.patch
new file mode 100644
index 000000000..6fa69b602
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0018-Catch-sdbusplus-exceptions-in-IPMI-net.patch
@@ -0,0 +1,49 @@
+From 4490ee7a9fd054640af7a9da3400f76195dc2880 Mon Sep 17 00:00:00 2001
+From: Yong Li <yong.b.li@linux.intel.com>
+Date: Sun, 16 Sep 2018 21:03:58 +0800
+Subject: [PATCH] Catch sdbusplus exceptions in IPMI net
+
+Missing the correct exception was causing issues with setting the IPV4
+address
+
+Change-Id: Ieaaacfcbaec82a0c3b110889817a7ceb9cda8d3c
+Signed-off-by: Dave Cobbley <david.j.cobbley@linux.intel.com>
+Signed-off-by: Yong Li <yong.b.li@linux.intel.com>
+---
+ transporthandler.cpp | 2 +-
+ utils.cpp | 5 +++--
+ 2 files changed, 4 insertions(+), 3 deletions(-)
+
+diff --git a/transporthandler.cpp b/transporthandler.cpp
+index 6f4ec3f..6cb3feb 100644
+--- a/transporthandler.cpp
++++ b/transporthandler.cpp
+@@ -1559,7 +1559,7 @@ void applyChanges(int channel)
+ ipmi::network::ETHERNET_INTERFACE, "IPv6AcceptRA",
+ (bool)channelConf->ipv6RouterAddressConfigControl);
+ }
+- catch (InternalFailure& e)
++ catch (sdbusplus::exception::exception& e)
+ {
+ log<level::ERR>(
+ "Failed to set network data", entry("PREFIX=%d", prefix),
+diff --git a/utils.cpp b/utils.cpp
+index 225b1cc..d10b5de 100644
+--- a/utils.cpp
++++ b/utils.cpp
+@@ -358,9 +358,10 @@ void deleteAllDbusObjects(sdbusplus::bus::bus& bus,
+ "Delete");
+ }
+ }
+- catch (InternalFailure& e)
++ catch (sdbusplus::exception::exception& e)
+ {
+- log<level::INFO>("Unable to delete the objects having",
++ log<level::INFO>("sdbusplus exception - Unable to delete the objects",
++ entry("ERROR=%s", e.what()),
+ entry("INTERFACE=%s", interface.c_str()),
+ entry("SERVICE=%s", serviceRoot.c_str()));
+ }
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0021-Implement-IPMI-Commmand-Get-Host-Restart-Cause.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0021-Implement-IPMI-Commmand-Get-Host-Restart-Cause.patch
new file mode 100644
index 000000000..af526c177
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0021-Implement-IPMI-Commmand-Get-Host-Restart-Cause.patch
@@ -0,0 +1,143 @@
+From c14e31ebc35e0bb7b843d84683f9f2698c9c08d7 Mon Sep 17 00:00:00 2001
+From: Yong Li <yong.b.li@linux.intel.com>
+Date: Sun, 16 Sep 2018 21:32:38 +0800
+Subject: [PATCH] Implement IPMI Commmand - Get Host Restart Cause.
+
+It supports to track the information about what
+action last caused the system to restart.
+Return value includes: restart_cause and channel_number.
+
+According to IPMI Spec, it includes 12 types as following:
+1. Unknown 0x0
+2. IpmiCommand 0x1
+3. ResetButton 0x2
+4. PowerButton 0x3
+5. WatchdogTimer 0x4
+6. OEM 0x5
+7. PowerPolicyAlwaysOn 0x6
+8. PowerPolicyPreviousState 0x7
+9. PEF-Reset 0x8
+10. PEF-PowerCycle 0x9
+11. SoftReset 0xA
+12. RTC-Wakeup 0xB
+
+Change-Id: Id3b32e271b85b5fc4c69d5ca40227f8f9c08ce48
+Signed-off-by: Kuiying Wang <kuiying.wang@intel.com>
+Signed-off-by: Yong Li <yong.b.li@linux.intel.com>
+---
+ chassishandler.cpp | 54 +++++++++++++++++++++++++++++++++++++++++++++++
+ chassishandler.hpp | 1 +
+ host-ipmid-whitelist.conf | 1 +
+ 3 files changed, 56 insertions(+)
+
+diff --git a/chassishandler.cpp b/chassishandler.cpp
+index 77af2dc..2a29755 100644
+--- a/chassishandler.cpp
++++ b/chassishandler.cpp
+@@ -107,6 +107,11 @@ static constexpr auto chassisPOHStateIntf =
+ "xyz.openbmc_project.State.PowerOnHours";
+ static constexpr auto pOHCounterProperty = "POHCounter";
+ static constexpr auto match = "chassis0";
++const static constexpr char* stateHostInterface =
++ "xyz.openbmc_project.State.Host";
++const static constexpr char* hostRestartCauseInterface =
++ "xyz.openbmc_project.State.Host.HostRestartCause";
++const static constexpr char* hostRestartCause = "HostRestartCause";
+ const static constexpr char chassisCapIntf[] =
+ "xyz.openbmc_project.Control.ChassisCapabilities";
+ const static constexpr char chassisCapFlagsProp[] = "CapabilitiesFlags";
+@@ -324,6 +329,13 @@ struct set_sys_boot_options_t
+ uint8_t data[SIZE_BOOT_OPTION];
+ } __attribute__((packed));
+
++struct GetSysRestartCauseResponse
++{
++ uint8_t restartCause;
++ uint8_t channelNum;
++
++} __attribute__((packed));
++
+ int getHostNetworkData(get_sys_boot_options_response_t* respptr)
+ {
+ ipmi::PropertyMap properties;
+@@ -1598,6 +1610,44 @@ ipmi_ret_t ipmi_chassis_set_sys_boot_options(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+ return rc;
+ }
+
++ipmi_ret_t ipmi_chassis_get_sys_restart_cause(
++ ipmi_netfn_t netfn, ipmi_cmd_t cmd, ipmi_request_t request,
++ ipmi_response_t response, ipmi_data_len_t data_len, ipmi_context_t context)
++{
++ ipmi_ret_t rc = IPMI_CC_OK;
++
++ GetSysRestartCauseResponse* resp = (GetSysRestartCauseResponse*)response;
++ std::fill(reinterpret_cast<uint8_t*>(resp),
++ reinterpret_cast<uint8_t*>(resp) + sizeof(*resp), 0);
++ if (*data_len != 0)
++ {
++ rc = IPMI_CC_REQ_DATA_LEN_INVALID;
++ return rc;
++ }
++
++ try
++ {
++ sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
++ ipmi::DbusObjectInfo hostObject =
++ ipmi::getDbusObject(bus, stateHostInterface);
++ ipmi::Value variant =
++ ipmi::getDbusProperty(bus, hostObject.second, hostObject.first,
++ hostRestartCauseInterface, hostRestartCause);
++ resp->restartCause = variant.get<uint8_t>();
++ }
++
++ catch (std::exception& e)
++ {
++ log<level::ERR>(e.what());
++ rc = IPMI_CC_UNSPECIFIED_ERROR;
++ return rc;
++ }
++ resp->channelNum = 0; // Fix to primary channel.
++ *data_len = sizeof(GetSysRestartCauseResponse);
++
++ return rc;
++}
++
+ ipmi_ret_t ipmiGetPOHCounter(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+ ipmi_request_t request, ipmi_response_t response,
+ ipmi_data_len_t data_len, ipmi_context_t context)
+@@ -1739,4 +1789,8 @@ void register_netfn_chassis_functions()
+ ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_SET_RESTORE_POLICY, NULL,
+ ipmi_chassis_set_power_restore_policy,
+ PRIVILEGE_OPERATOR);
++
++ // <get Host Restart Cause>
++ ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_GET_SYS_RESTART_CAUSE, NULL,
++ ipmi_chassis_get_sys_restart_cause, PRIVILEGE_USER);
+ }
+diff --git a/chassishandler.hpp b/chassishandler.hpp
+index 0c6d5a2..e37c4f1 100644
+--- a/chassishandler.hpp
++++ b/chassishandler.hpp
+@@ -17,6 +17,7 @@ enum ipmi_netfn_chassis_cmds
+ // Set Power Restore Policy
+ IPMI_CMD_SET_RESTORE_POLICY = 0x06,
+ // Get capability bits
++ IPMI_CMD_GET_SYS_RESTART_CAUSE = 0x07,
+ IPMI_CMD_SET_SYS_BOOT_OPTIONS = 0x08,
+ IPMI_CMD_GET_SYS_BOOT_OPTIONS = 0x09,
+ IPMI_CMD_GET_POH_COUNTER = 0x0F,
+diff --git a/host-ipmid-whitelist.conf b/host-ipmid-whitelist.conf
+index db54a49..827e2dc 100644
+--- a/host-ipmid-whitelist.conf
++++ b/host-ipmid-whitelist.conf
+@@ -3,6 +3,7 @@
+ 0x00:0x02 //<Chassis>:<Chassis Control>
+ 0x00:0x05 //<Chassis>:<Set Chassis Capabilities>
+ 0x00:0x06 //<Chassis>:<Set Power Restore Policy>
++0x00:0x07 //<Chassis>:<Get System Restart Cause>
+ 0x00:0x08 //<Chassis>:<Set System Boot Options>
+ 0x00:0x09 //<Chassis>:<Get System Boot Options>
+ 0x00:0x0F //<Chassis>:<Get POH Counter Command>
+--
+2.7.4
+
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/0048-Implement-IPMI-Master-Write-Read-command.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0048-Implement-IPMI-Master-Write-Read-command.patch
new file mode 100644
index 000000000..4018dbffe
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0048-Implement-IPMI-Master-Write-Read-command.patch
@@ -0,0 +1,322 @@
+From cd25f43461b41b74d19cd1f93ce301df9c3bd4f2 Mon Sep 17 00:00:00 2001
+From: Yong Li <yong.b.li@linux.intel.com>
+Date: Fri, 21 Sep 2018 09:21:14 +0800
+Subject: [PATCH] Implement IPMI Master Write-Read command
+
+This command can be used for low-level I2C/SMBus write, read, or write-read
+accesses to the IPMB or private busses behind a management controller.
+
+The command can also be used for providing low-level access to devices
+that provide an SMBus slave interface.
+
+Signed-off-by: Yong Li <yong.b.li@linux.intel.com>
+---
+ apphandler.cpp | 236 ++++++++++++++++++++++++++++++++++++++++++++++
+ apphandler.hpp | 1 +
+ host-ipmid-whitelist.conf | 1 +
+ 3 files changed, 238 insertions(+)
+
+diff --git a/apphandler.cpp b/apphandler.cpp
+index 17aff2a..2fe79f6 100644
+--- a/apphandler.cpp
++++ b/apphandler.cpp
+@@ -8,6 +8,14 @@
+ #include "types.hpp"
+ #include "utils.hpp"
+
++#include <fcntl.h>
++#include <linux/i2c-dev.h>
++#include <linux/i2c.h>
++#include <sys/ioctl.h>
++#include <sys/stat.h>
++#include <sys/types.h>
++#include <unistd.h>
++
+ #include <arpa/inet.h>
+ #include <host-ipmid/ipmid-api.h>
+ #include <limits.h>
+@@ -55,6 +63,8 @@ constexpr auto bmc_guid_interface = "xyz.openbmc_project.Common.UUID";
+ constexpr auto bmc_guid_property = "UUID";
+ constexpr auto bmc_guid_len = 16;
+
++static constexpr uint8_t maxIPMIWriteReadSize = 144;
++
+ static constexpr auto redundancyIntf =
+ "xyz.openbmc_project.Software.RedundancyPriority";
+ static constexpr auto versionIntf = "xyz.openbmc_project.Software.Version";
+@@ -86,6 +96,34 @@ typedef struct
+ uint8_t aux[4];
+ } __attribute__((packed)) ipmi_device_id_t;
+
++typedef struct
++{
++ uint8_t busId;
++ uint8_t slaveAddr;
++ uint8_t readCount;
++} __attribute__((packed)) ipmiI2cRwReq;
++
++typedef struct
++{
++ uint8_t busId;
++ uint8_t slaveAddr;
++ std::vector<uint8_t> data;
++} ipmiMasterRwWhitelist;
++
++static std::vector<ipmiMasterRwWhitelist>& getWhiteList()
++{
++ static std::vector<ipmiMasterRwWhitelist> rwWhiteList;
++ return rwWhiteList;
++}
++
++static constexpr const char* whiteListFilename =
++ "/usr/share/ipmi-providers/master_write_read_white_list.json";
++
++static constexpr const char* filtersStr = "filters";
++static constexpr const char* busIdStr = "busId";
++static constexpr const char* slaveAddrStr = "slaveAddr";
++static constexpr const char* cmdStr = "command";
++
+ /**
+ * @brief Returns the Version info from primary s/w object
+ *
+@@ -1089,8 +1127,195 @@ writeResponse:
+ return IPMI_CC_OK;
+ }
+
++static int loadI2CWhiteList()
++{
++ nlohmann::json data = nullptr;
++ std::ifstream jsonFile(whiteListFilename);
++
++ if (!jsonFile.good())
++ {
++ log<level::WARNING>("whitelist file not found!");
++ return -1;
++ }
++
++ try
++ {
++ data = nlohmann::json::parse(jsonFile, nullptr, false);
++ }
++ catch (nlohmann::json::parse_error& e)
++ {
++ log<level::ERR>("Corrupted whitelist config file",
++ entry("MSG: %s", e.what()));
++ return -1;
++ }
++
++ try
++ {
++ unsigned int i = 0;
++ nlohmann::json filters = data[filtersStr].get<nlohmann::json>();
++ getWhiteList().resize(filters.size());
++
++ for (const auto& it : filters.items())
++ {
++ nlohmann::json filter = it.value();
++ if (filter.is_null())
++ {
++ log<level::ERR>("Incorrect filter");
++ return -1;
++ }
++
++ getWhiteList()[i].busId =
++ std::stoul(filter[busIdStr].get<std::string>(), nullptr, 16);
++
++ getWhiteList()[i].slaveAddr = std::stoul(
++ filter[slaveAddrStr].get<std::string>(), nullptr, 16);
++
++ std::string command = filter[cmdStr].get<std::string>();
++
++ log<level::DEBUG>("IPMI I2C whitelist ", entry("INDEX=%d", i),
++ entry("BUS=%d", getWhiteList()[i].busId),
++ entry("ADDR=0x%x", getWhiteList()[i].slaveAddr),
++ entry("LEN=0x%x", command.length()),
++ entry("COMMAND=[%s]", command.c_str()));
++
++ // convert data string
++ std::istringstream iss(command);
++ std::string token;
++ while (std::getline(iss, token, ' '))
++ {
++ log<level::DEBUG>("IPMI I2C command\n",
++ entry("TOKEN=%s", token.c_str()));
++ getWhiteList()[i].data.emplace_back(
++ std::stoul(token, nullptr, 16));
++ }
++ i++;
++ }
++ }
++ catch (std::exception& e)
++ {
++ log<level::ERR>("unexpected exception", entry("ERROR=%s", e.what()));
++ return -1;
++ }
++ return 0;
++}
++
++ipmi_ret_t ipmiMasterWriteRead(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
++ ipmi_request_t request, ipmi_response_t response,
++ ipmi_data_len_t data_len, ipmi_context_t context)
++{
++ bool foundInList = false;
++ int ret = 0;
++ i2c_rdwr_ioctl_data msgRdwr = {0};
++ i2c_msg i2cmsg[2] = {0};
++ ipmiI2cRwReq* reqi2c = reinterpret_cast<ipmiI2cRwReq*>(request);
++
++ if (*data_len <= sizeof(ipmiI2cRwReq))
++ {
++ log<level::ERR>("Failed in request", entry("LEN=%d", *data_len));
++ *data_len = 0;
++ return IPMI_CC_REQ_DATA_LEN_INVALID;
++ }
++
++ if (reqi2c->readCount > maxIPMIWriteReadSize)
++ {
++ log<level::ERR>("Failed in request", entry("R=%d", reqi2c->readCount));
++ *data_len = 0;
++ return IPMI_CC_PARM_OUT_OF_RANGE;
++ }
++
++ uint8_t* resptr = reinterpret_cast<uint8_t*>(response);
++ uint8_t busId = (reqi2c->busId & 0xFF) >> 1;
++ // Convert the I2C address from 7-bit format
++ uint8_t i2cAddr = reqi2c->slaveAddr >> 1;
++ size_t writeCount = *data_len - sizeof(ipmiI2cRwReq);
++
++ log<level::DEBUG>(
++ "INPUT: ", entry("LEN=%d", *data_len), entry("ID=0x%x", busId),
++ entry("ADDR=0x%x", reqi2c->slaveAddr), entry("R=%d", reqi2c->readCount),
++ entry("W=%d", writeCount));
++
++ *data_len = 0;
++
++ std::vector<uint8_t> inBuf(reqi2c->readCount);
++ std::vector<uint8_t> outBuf(writeCount);
++ uint8_t* reqptr = reinterpret_cast<uint8_t*>(request);
++
++ reqptr += sizeof(ipmiI2cRwReq);
++ std::copy(reqptr, reqptr + writeCount, outBuf.begin());
++
++ log<level::DEBUG>("checking list ", entry("SIZE=%d", getWhiteList().size()));
++ // command whitelist checking
++ for (unsigned int i = 0; i < getWhiteList().size(); i++)
++ {
++ // TODO add wildchard/regex support
++ if ((busId == getWhiteList()[i].busId) &&
++ (i2cAddr == getWhiteList()[i].slaveAddr) &&
++ (outBuf == getWhiteList()[i].data))
++ {
++ log<level::DEBUG>("In whitelist");
++ foundInList = true;
++ break;
++ }
++ }
++
++ if (!foundInList)
++ {
++ log<level::ERR>("Request blocked!", entry("BUS=%d", busId),
++ entry("ADDR=0x%x", reqi2c->slaveAddr));
++ return IPMI_CC_INVALID_FIELD_REQUEST;
++ }
++
++ log<level::DEBUG>("IPMI Master WriteRead ", entry("BUS=%d", busId),
++ entry("ADDR=0x%x", reqi2c->slaveAddr),
++ entry("R=%d", reqi2c->readCount),
++ entry("W=%d", writeCount));
++
++ std::string i2cBus = "/dev/i2c-" + std::to_string(busId);
++
++ int i2cDev = ::open(i2cBus.c_str(), O_RDWR | O_CLOEXEC);
++ if (i2cDev < 0)
++ {
++ log<level::ERR>("Failed in opening i2c device",
++ entry("BUS=%s", i2cBus.c_str()));
++ return IPMI_CC_UNSPECIFIED_ERROR;
++ }
++
++ // write message
++ i2cmsg[0].addr = i2cAddr;
++ i2cmsg[0].flags = 0x00;
++ i2cmsg[0].len = writeCount;
++ i2cmsg[0].buf = outBuf.data();
++
++ // read message
++ i2cmsg[1].addr = i2cAddr;
++ i2cmsg[1].flags = I2C_M_RD;
++ i2cmsg[1].len = reqi2c->readCount;
++ i2cmsg[1].buf = inBuf.data();
++
++ msgRdwr.msgs = i2cmsg;
++ msgRdwr.nmsgs = 2;
++
++ ret = ::ioctl(i2cDev, I2C_RDWR, &msgRdwr);
++ ::close(i2cDev);
++
++ // TODO add completion code support
++ if (ret < 0)
++ {
++ log<level::ERR>("RDWR ioctl error", entry("RET=%d", ret));
++ return IPMI_CC_UNSPECIFIED_ERROR;
++ }
++
++ *data_len = msgRdwr.msgs[1].len;
++ std::copy(msgRdwr.msgs[1].buf, msgRdwr.msgs[1].buf + msgRdwr.msgs[1].len,
++ resptr);
++
++ return IPMI_CC_OK;
++}
++
+ void register_netfn_app_functions()
+ {
++ int ret = -1;
++
+ // <Get BT Interface Capabilities>
+ ipmi_register_callback(NETFUN_APP, IPMI_CMD_GET_CAP_BIT, NULL,
+ ipmi_app_get_bt_capabilities, PRIVILEGE_USER);
+@@ -1145,6 +1370,17 @@ void register_netfn_app_functions()
+ ipmi_app_channel_info, PRIVILEGE_USER);
+ #endif
+
++ ret = loadI2CWhiteList();
++ log<level::DEBUG>("i2c white list is loaded", entry("RET=%d", ret),
++ entry("SIZE=%d", getWhiteList().size()));
++ if (ret == 0)
++ {
++ log<level::DEBUG>("Register Master RW command");
++ // <Master Write Read Command>
++ ipmi_register_callback(NETFUN_APP, IPMI_CMD_MASTER_WRITE_READ, NULL,
++ ipmiMasterWriteRead, PRIVILEGE_OPERATOR);
++ }
++
+ // <Get System GUID Command>
+ ipmi_register_callback(NETFUN_APP, IPMI_CMD_GET_SYS_GUID, NULL,
+ ipmi_app_get_sys_guid, PRIVILEGE_USER);
+diff --git a/apphandler.hpp b/apphandler.hpp
+index d4dd8e8..f9e5c59 100644
+--- a/apphandler.hpp
++++ b/apphandler.hpp
+@@ -19,6 +19,7 @@ enum ipmi_netfn_app_cmds
+ IPMI_CMD_SET_CHAN_ACCESS = 0x40,
+ IPMI_CMD_GET_CHANNEL_ACCESS = 0x41,
+ IPMI_CMD_GET_CHAN_INFO = 0x42,
++ IPMI_CMD_MASTER_WRITE_READ = 0x52,
+ IPMI_CMD_GET_CHAN_CIPHER_SUITES = 0x54,
+ IPMI_CMD_SET_SYSTEM_INFO = 0x58,
+ IPMI_CMD_GET_SYSTEM_INFO = 0x59,
+diff --git a/host-ipmid-whitelist.conf b/host-ipmid-whitelist.conf
+index c7eb2d8..22a2a3c 100644
+--- a/host-ipmid-whitelist.conf
++++ b/host-ipmid-whitelist.conf
+@@ -25,6 +25,7 @@
+ 0x06:0x36 //<App>:<Get BT Interface Capabilities>
+ 0x06:0x37 //<App>:<Get System GUID>
+ 0x06:0x42 //<App>:<Get Channel Info Command>
++0x06:0x52 //<App>:<Master Write Read Command>
+ 0x06:0x54 //<App>:<Get Channel Cipher Suites>
+ 0x0A:0x10 //<Storage>:<Get FRU Inventory Area Info>
+ 0x0A:0x11 //<Storage>:<Read FRU Data>
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0049-Fix-Unspecified-error-on-ipmi-restart-cause-command.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0049-Fix-Unspecified-error-on-ipmi-restart-cause-command.patch
new file mode 100644
index 000000000..aba5eb095
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0049-Fix-Unspecified-error-on-ipmi-restart-cause-command.patch
@@ -0,0 +1,71 @@
+From 59287a8869b5253a1b4203e0cc8a92f063dcc7e6 Mon Sep 17 00:00:00 2001
+From: Yong Li <yong.b.li@linux.intel.com>
+Date: Tue, 25 Sep 2018 16:08:22 +0800
+Subject: [PATCH] Fix "Unspecified error" on ipmi restart cause command
+
+Needs to convert the dbus value(enum) into ipmi value(uint8)
+
+Tested by:
+ipmitool chassis restart_cause
+
+Signed-off-by: Yong Li <yong.b.li@linux.intel.com>
+---
+ chassishandler.cpp | 28 ++++++++++++++++++++++++++--
+ 1 file changed, 26 insertions(+), 2 deletions(-)
+
+diff --git a/chassishandler.cpp b/chassishandler.cpp
+index 40eb4f5..c3d4931 100644
+--- a/chassishandler.cpp
++++ b/chassishandler.cpp
+@@ -106,7 +106,7 @@ static constexpr auto match = "chassis0";
+ const static constexpr char* stateHostInterface =
+ "xyz.openbmc_project.State.Host";
+ const static constexpr char* hostRestartCauseInterface =
+- "xyz.openbmc_project.State.Host.HostRestartCause";
++ "xyz.openbmc_project.State.Host";
+ const static constexpr char* hostRestartCause = "HostRestartCause";
+ const static constexpr char chassisCapIntf[] =
+ "xyz.openbmc_project.Control.ChassisCapabilities";
+@@ -1764,6 +1764,26 @@ ipmi_ret_t ipmi_chassis_set_sys_boot_options(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+ return rc;
+ }
+
++namespace restart_cause
++{
++
++using namespace sdbusplus::xyz::openbmc_project::State::server;
++
++std::map<Host::RestartCause, uint8_t> dbusToIpmi = {
++ {Host::RestartCause::Unknown, 0x0},
++ {Host::RestartCause::IpmiCommand, 0x1},
++ {Host::RestartCause::ResetButton, 0x2},
++ {Host::RestartCause::PowerButton, 0x3},
++ {Host::RestartCause::WatchdogTimer, 0x4},
++ {Host::RestartCause::OEM, 0x5},
++ {Host::RestartCause::PowerPolicyAlwaysOn, 0x6},
++ {Host::RestartCause::PowerPolicyPreviousState, 0x7},
++ {Host::RestartCause::PEFReset, 0x8},
++ {Host::RestartCause::PEFPowerCycle, 0x9},
++ {Host::RestartCause::SoftReset, 0xa},
++ {Host::RestartCause::RTCWakeup, 0xb}};
++} // namespace restart_cause
++
+ ipmi_ret_t ipmi_chassis_get_sys_restart_cause(
+ ipmi_netfn_t netfn, ipmi_cmd_t cmd, ipmi_request_t request,
+ ipmi_response_t response, ipmi_data_len_t data_len, ipmi_context_t context)
+@@ -1787,7 +1807,11 @@ ipmi_ret_t ipmi_chassis_get_sys_restart_cause(
+ ipmi::Value variant =
+ ipmi::getDbusProperty(bus, hostObject.second, hostObject.first,
+ hostRestartCauseInterface, hostRestartCause);
+- resp->restartCause = variant.get<uint8_t>();
++
++ std::string restartCause =
++ sdbusplus::message::variant_ns::get<std::string>(variant);
++ resp->restartCause = restart_cause::dbusToIpmi.at(
++ restart_cause::Host::convertRestartCauseFromString(restartCause));
+ }
+
+ catch (std::exception& e)
+--
+2.7.4
+
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/0051-Fix-Set-LAN-Config-to-work-without-SetInProgress.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0051-Fix-Set-LAN-Config-to-work-without-SetInProgress.patch
new file mode 100644
index 000000000..3990c6b5c
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0051-Fix-Set-LAN-Config-to-work-without-SetInProgress.patch
@@ -0,0 +1,142 @@
+From cae9e21f88e6f12c80c89402473a17a10258c843 Mon Sep 17 00:00:00 2001
+From: Richard Marian Thomaiyar <richard.marian.thomaiyar@linux.intel.com>
+Date: Thu, 17 Jan 2019 21:22:30 +0530
+Subject: [PATCH] Fix: Set LAN Config to work without SetInProgress
+
+Set LAN Configuration parameters in up-stream code works
+with SetInProgress (parameter selector 0), to be marked
+as SET_IN_PROGRESS before fields update, and SET_COMPLETE to
+make the changes effective. This is not mandatory as per
+IPMI Spec, and we must support individual fields update.
+Fix:
+1. After SET_COMPLETE for parameter selector, changes has
+to be applied immediately, and doesn't require to rely on
+network timer, as purpose of this logic itself is to stage
+and commit.
+2. Allow individual parameter changes to take effect based
+on timer. For the time being reduced the timer to 5 sec
+to have quicker turn-around and group things together.
+
+TODO:
+Still need to introduce lock between ChannelConfig variable
+between Timer & Get / Set LAN Configuration command to avoid
+race condition
+
+Unit-Test:
+1. Verified the BIOS Setup page, able to set the IPV4 to static
+IP, afte disabling IPV6, and configuring IPV4 to static, after
+save and reset, the changes of IPV4 static is preserved.
+
+Change-Id: I7c2edad2861b5dba5ad1ca97cc5e39ac02871746
+Signed-off-by: Richard Marian Thomaiyar <richard.marian.thomaiyar@linux.intel.com>
+---
+ transporthandler.cpp | 54 ++++++++++++++++++++++++++++++++++++----------------
+ transporthandler.hpp | 2 ++
+ 2 files changed, 40 insertions(+), 16 deletions(-)
+
+Index: phosphor-host-ipmid.clean/transporthandler.cpp
+===================================================================
+--- phosphor-host-ipmid.clean.orig/transporthandler.cpp
++++ phosphor-host-ipmid.clean/transporthandler.cpp
+@@ -399,6 +399,41 @@ struct set_lan_t
+ uint8_t data[8]; // Per IPMI spec, not expecting more than this size
+ } __attribute__((packed));
+
++ipmi_ret_t checkAndUpdateNetwork(int channel)
++{
++ auto channelConf = getChannelConfig(channel);
++ using namespace std::chrono_literals;
++ // time to wait before applying the network changes.
++ constexpr auto networkTimeout = 5000000us; // 5 sec
++
++ if (channelConf->lan_set_in_progress == SET_COMPLETE &&
++ ((channelConf->flush == false) ||
++ (channelConf->updateInProgress == true)))
++ {
++ channelConf->flush = true;
++ // used to indicate that network timer update is in progress.
++ channelConf->updateInProgress = true;
++ if (!networkTimer)
++ {
++ log<level::ERR>("Network timer is not instantiated");
++ return IPMI_CC_UNSPECIFIED_ERROR;
++ }
++ // start/restart the timer
++ // TODO: Need to implement locking mechansim between networkTimer &
++ // get/set to avoid race condition.
++ networkTimer->start(networkTimeout);
++ }
++ else if (channelConf->lan_set_in_progress == SET_COMPLETE &&
++ channelConf->flush == true &&
++ channelConf->updateInProgress == false)
++ {
++ // Apply the network changes immediately, if proper SET_IN_PROGRESS,
++ // followed by SET_COMPLETE is issued.
++ applyChanges(channel);
++ }
++ return IPMI_CC_OK;
++}
++
+ ipmi_ret_t ipmi_transport_set_lan(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+ ipmi_request_t request,
+ ipmi_response_t response,
+@@ -406,12 +441,6 @@ ipmi_ret_t ipmi_transport_set_lan(ipmi_n
+ ipmi_context_t context)
+ {
+ ipmi_ret_t rc = IPMI_CC_OK;
+-
+- using namespace std::chrono_literals;
+-
+- // time to wait before applying the network changes.
+- constexpr auto networkTimeout = 10000000us; // 10 sec
+-
+ char ipaddr[INET_ADDRSTRLEN];
+ char netmask[INET_ADDRSTRLEN];
+ char gateway[INET_ADDRSTRLEN];
+@@ -543,15 +572,6 @@ ipmi_ret_t ipmi_transport_set_lan(ipmi_n
+ entry("ADDRESS=%s", channelConf->ipaddr.c_str()),
+ entry("GATEWAY=%s", channelConf->gateway.c_str()),
+ entry("VLAN=%d", channelConf->vlanID));
+-
+- if (!networkTimer)
+- {
+- log<level::ERR>("Network timer is not instantiated");
+- return IPMI_CC_UNSPECIFIED_ERROR;
+- }
+-
+- // start/restart the timer
+- networkTimer->start(networkTimeout);
+ }
+ else if (reqptr->data[0] == SET_IN_PROGRESS) // Set In Progress
+ {
+@@ -680,8 +700,10 @@ ipmi_ret_t ipmi_transport_set_lan(ipmi_n
+ default:
+ {
+ rc = IPMI_CC_PARM_NOT_SUPPORTED;
++ return rc;
+ }
+ }
++ rc = checkAndUpdateNetwork(channel);
+
+ return rc;
+ }
+Index: phosphor-host-ipmid.clean/transporthandler.hpp
+===================================================================
+--- phosphor-host-ipmid.clean.orig/transporthandler.hpp
++++ phosphor-host-ipmid.clean/transporthandler.hpp
+@@ -140,6 +140,7 @@ struct ChannelConfig_t
+ // vlan id is in 12 bits and the 16th bit is for enable mask.
+ uint32_t vlanID = ipmi::network::VLAN_ID_MASK;
+ uint8_t lan_set_in_progress = SET_COMPLETE;
++ uint8_t updateInProgress = false;
+ bool flush = false;
+
+ // IPV6 parameters
+@@ -165,6 +166,7 @@ struct ChannelConfig_t
+ vlanID = ipmi::network::VLAN_ID_MASK;
+ ipsrc = ipmi::network::IPOrigin::UNSPECIFIED;
+ lan_set_in_progress = SET_COMPLETE;
++ updateInProgress = false;
+ flush = false;
+
+ // IPv6
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..2a4cc9bb1
--- /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 9ed3fd11047f8c360b7d808946939ef280813811 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 0a61e63..6e50684 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 = "/org/openbmc/HostIpmi/1";
++constexpr const char* IPMI_INTERFACE = "org.openbmc.HostIpmi";
+
+ // For throwing exceptions
+ using namespace phosphor::logging;
+@@ -107,6 +109,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
+@@ -116,9 +132,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
+@@ -132,9 +145,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.16.2
+
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..d855eaa5b
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/phosphor-ipmi-host.service
@@ -0,0 +1,26 @@
+[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-host0-restriction_mode.service
+After=mapper-wait@-xyz-openbmc_project-control-host0-restriction_mode.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..a92fc833b
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host_%.bbappend
@@ -0,0 +1,29 @@
+FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
+
+SRC_URI += "file://phosphor-ipmi-host.service \
+ file://0002-Modify-dbus-interface-for-power-control.patch \
+ file://0003-Modify-dbus-interface-for-chassis-control.patch \
+ file://0009-IPv6-Network-changes.patch \
+ file://0010-fix-get-system-GUID-ipmi-command.patch \
+ file://0012-ipmi-set-get-boot-options.patch \
+ file://0013-ipmi-add-set-bios-id-to-whitelist.patch \
+ file://0014-Enable-get-device-guid-ipmi-command.patch \
+ file://0016-add-better-sdbusplus-exception-handling.patch \
+ file://0018-Catch-sdbusplus-exceptions-in-IPMI-net.patch \
+ file://0021-Implement-IPMI-Commmand-Get-Host-Restart-Cause.patch \
+ file://0039-ipmi-add-oem-command-get-AIC-FRU-to-whitelist.patch \
+ file://0048-Implement-IPMI-Master-Write-Read-command.patch \
+ file://0049-Fix-Unspecified-error-on-ipmi-restart-cause-command.patch \
+ file://0050-enable-6-oem-commands.patch \
+ file://0051-Fix-Set-LAN-Config-to-work-without-SetInProgress.patch \
+ file://0053-Fix-keep-looping-issue-when-entering-OS.patch \
+ "
+
+do_install_append(){
+ install -d ${D}${includedir}/phosphor-ipmi-host
+ install -d ${D}${libdir}/phosphor-ipmi-host
+ install -m 0644 -D ${S}/*.h ${D}${includedir}/phosphor-ipmi-host
+ install -m 0644 -D ${S}/*.hpp ${D}${includedir}/phosphor-ipmi-host
+ install -m 0644 -D ${S}/utils.cpp ${D}${libdir}/phosphor-ipmi-host
+
+}
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..d5d38a0ce
--- /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 = "25e85c79257723b1cb754c20299196685373ce24"
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-kcs/org.openbmc.HostIpmi.SMM.service b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-kcs/org.openbmc.HostIpmi.SMM.service
new file mode 100644
index 000000000..288fa422d
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-kcs/org.openbmc.HostIpmi.SMM.service
@@ -0,0 +1,13 @@
+[Unit]
+Description=Phosphor IPMI KCS DBus Bridge(SMM)
+After=phosphor-ipmi-host.service
+
+[Service]
+Restart=always
+ExecStart={sbindir}/kcsbridged --d="/dev/ipmi-kcs4" --i="SMM"
+SyslogIdentifier=kcsbridged_SMM
+Type=dbus
+BusName={BUSNAME}
+
+[Install]
+WantedBy={SYSTEMD_DEFAULT_TARGET}
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-kcs/org.openbmc.HostIpmi.service b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-kcs/org.openbmc.HostIpmi.service
new file mode 100644
index 000000000..177062e27
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-kcs/org.openbmc.HostIpmi.service
@@ -0,0 +1,13 @@
+[Unit]
+Description=Phosphor IPMI KCS DBus Bridge(SMS)
+After=phosphor-ipmi-host.service
+
+[Service]
+Restart=always
+ExecStart={sbindir}/kcsbridged --d="/dev/ipmi-kcs3"
+SyslogIdentifier=kcsbridged
+Type=dbus
+BusName={BUSNAME}
+
+[Install]
+WantedBy={SYSTEMD_DEFAULT_TARGET}
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..ac7a03108
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-kcs_%.bbappend
@@ -0,0 +1,9 @@
+FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
+
+DBUS_SERVICE_${PN} += "org.openbmc.HostIpmi.SMM.service"
+
+SYSTEMD_SUBSTITUTIONS_remove = "KCS_DEVICE:${KCS_DEVICE}:${DBUS_SERVICE_${PN}}"
+
+SRC_URI = "git://github.com/openbmc/kcsbridge.git"
+SRCREV = "17a2ab7f39a78ff0603aa68cf35108ea94eb442f"
+
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..7225c7529
--- /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/0007-Adding-support-for-GetSessionInfo-command.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-net/0007-Adding-support-for-GetSessionInfo-command.patch
new file mode 100644
index 000000000..fda7ed2ca
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-net/0007-Adding-support-for-GetSessionInfo-command.patch
@@ -0,0 +1,421 @@
+From f5c7d30be4a097998d9390614c0faa2d77109ca5 Mon Sep 17 00:00:00 2001
+From: ssekar <suryakanth.sekar@linux.intel.com>
+Date: Wed, 12 Dec 2018 16:04:15 +0530
+Subject: [PATCH] Adding support for GetSessionInfo command
+
+Description: user can get all session info (remote ip,port,
+session id, priv, etc) using this command.
+
+Verification :we can get all active and non active session
+info by session handle session id.
+Updated the Remote IP addr and Port update for sessioninfo.
+Unit testing are done.
+
+Change-Id: I662ef2b9f0c1d6bda331eb6481d7b9f34534541b
+Signed-off-by: ssekar <suryakanth.sekar@linux.intel.com>
+---
+ comm_module.cpp | 8 +++
+ command/session_cmds.cpp | 147 +++++++++++++++++++++++++++++++++++++++
+ command/session_cmds.hpp | 55 +++++++++++++++
+ message_handler.cpp | 1 +
+ sessions_manager.cpp | 55 +++++++++++++++
+ sessions_manager.hpp | 7 ++
+ socket_channel.cpp | 27 ++++++-
+ socket_channel.hpp | 3 +-
+ 8 files changed, 301 insertions(+), 2 deletions(-)
+
+Index: phosphor-net-ipmid.clean/comm_module.cpp
+===================================================================
+--- phosphor-net-ipmid.clean.orig/comm_module.cpp
++++ phosphor-net-ipmid.clean/comm_module.cpp
+@@ -53,6 +53,14 @@ void sessionSetupCommands()
+ &closeSession,
+ session::Privilege::CALLBACK,
+ false},
++ // Session Info Command
++ {
++ {
++ (static_cast<uint32_t>(message::PayloadType::IPMI) << 16) |
++ static_cast<uint16_t>(command::NetFns::APP) | 0x3D
++ },
++ &getSessionInfo, session::Privilege::USER, false
++ },
+ };
+
+ for (auto& iter : commands)
+Index: phosphor-net-ipmid.clean/command/session_cmds.cpp
+===================================================================
+--- phosphor-net-ipmid.clean.orig/command/session_cmds.cpp
++++ phosphor-net-ipmid.clean/command/session_cmds.cpp
+@@ -5,11 +5,19 @@
+
+ #include <host-ipmid/ipmid-api.h>
+
++#include <iostream>
+ #include <user_channel/channel_layer.hpp>
+ #include <user_channel/user_layer.hpp>
+
+ namespace command
+ {
++// Defined as per IPMI sepcification
++static constexpr uint8_t searchCurrentSession = 0x00;
++static constexpr uint8_t searchSessionByHandle = 0xFE;
++static constexpr uint8_t searchSessionByID = 0xFF;
++
++static constexpr uint8_t ipmi15VerSession = 0x00;
++static constexpr uint8_t ipmi20VerSession = 0x01;
+
+ std::vector<uint8_t>
+ setSessionPrivilegeLevel(const std::vector<uint8_t>& inPayload,
+@@ -110,4 +118,143 @@ std::vector<uint8_t> closeSession(const
+ return outPayload;
+ }
+
++std::vector<uint8_t> getSessionInfo(const std::vector<uint8_t>& inPayload,
++ const message::Handler& handler)
++
++{
++ std::vector<uint8_t> outPayload(sizeof(GetSessionInfoResponse));
++ auto request =
++ reinterpret_cast<const GetSessionInfoRequest*>(inPayload.data());
++ auto response =
++ reinterpret_cast<GetSessionInfoResponse*>(outPayload.data());
++ uint32_t reqSessionID = handler.sessionID;
++ response->completionCode = IPMI_CC_OK;
++ if (inPayload.size() == 1 && request->sessionIndex != 0)
++ {
++ if (request->sessionIndex <= session::MAX_SESSION_COUNT)
++ {
++ reqSessionID = std::get<session::Manager&>(singletonPool)
++ .getSessionIDbyHandle(request->sessionIndex);
++ }
++ else
++ {
++ response->completionCode = IPMI_CC_INVALID_FIELD_REQUEST;
++ outPayload.resize(sizeof(response->completionCode));
++ return std::move(outPayload);
++ }
++ }
++
++ // Here we look for session info according to session index parameter
++ switch (request->sessionIndex)
++ {
++ // Look for current active session which this cmd is received over
++ case searchCurrentSession:
++ // Request data should only contain session index byte
++ if (inPayload.size() != 1)
++ {
++ response->completionCode = IPMI_CC_REQ_DATA_LEN_INVALID;
++ outPayload.resize(sizeof(response->completionCode));
++ return std::move(outPayload);
++ }
++ // To look for current active session which the command came over,
++ // the session ID cannot be 0.
++ if (0 == reqSessionID)
++ {
++ response->completionCode = IPMI_CC_INVALID_FIELD_REQUEST;
++ outPayload.resize(sizeof(response->completionCode));
++ return std::move(outPayload);
++ }
++ break;
++ case searchSessionByHandle:
++ // Request data should only contain session index byte and Session
++ // handle
++ if (inPayload.size() != 2)
++ {
++ response->completionCode = IPMI_CC_REQ_DATA_LEN_INVALID;
++ outPayload.resize(sizeof(response->completionCode));
++ return std::move(outPayload);
++ }
++
++ // Retrieve session id based on session handle
++ if (request->sessionHandle <= session::MAX_SESSION_COUNT)
++ {
++ reqSessionID =
++ std::get<session::Manager&>(singletonPool)
++ .getSessionIDbyHandle(request->sessionHandle);
++ }
++ else
++ {
++ response->completionCode = IPMI_CC_INVALID_FIELD_REQUEST;
++ outPayload.resize(sizeof(response->completionCode));
++ return std::move(outPayload);
++ }
++ break;
++ case searchSessionByID:
++ // Request data should only contain session index byte and Session
++ // handle
++ if (inPayload.size() != sizeof(GetSessionInfoRequest))
++ {
++ response->completionCode = IPMI_CC_REQ_DATA_LEN_INVALID;
++ outPayload.resize(sizeof(response->completionCode));
++ return std::move(outPayload);
++ }
++ reqSessionID = endian::from_ipmi(request->sessionID);
++
++ break;
++ default:
++ if (inPayload.size() != 1)
++ {
++ response->completionCode = IPMI_CC_REQ_DATA_LEN_INVALID;
++ outPayload.resize(sizeof(response->completionCode));
++ return std::move(outPayload);
++ }
++ }
++
++ response->totalSessionCount = session::MAX_SESSION_COUNT;
++ response->activeSessioncount =
++ std::get<session::Manager&>(singletonPool).getNoOfActiveSession();
++ response->sessionHandle = 0;
++ if (reqSessionID != 0)
++ {
++
++ std::shared_ptr<session::Session> sessionInfo;
++ try
++ {
++ sessionInfo = std::get<session::Manager&>(singletonPool)
++ .getSession(reqSessionID);
++ }
++ catch (std::exception& e)
++ {
++ response->completionCode = IPMI_CC_UNSPECIFIED_ERROR;
++ outPayload.resize(sizeof(response->completionCode));
++ return std::move(outPayload);
++ }
++ response->sessionHandle = std::get<session::Manager&>(singletonPool)
++ .getSessionHandle(reqSessionID);
++ uint8_t userId = ipmi::ipmiUserGetUserId(sessionInfo->userName);
++ if (userId == ipmi::invalidUserId)
++ {
++ response->completionCode = IPMI_CC_UNSPECIFIED_ERROR;
++ outPayload.resize(sizeof(response->completionCode));
++ return std::move(outPayload);
++ }
++ response->userID = userId; // userId;
++ response->privLevel = static_cast<uint8_t>(sessionInfo->curPrivLevel);
++ response->chanNum = sessionInfo->chNum; // byte7 3:0
++ response->ipmiVer = ipmi20VerSession; // byte7 7:4
++ response->remoteIpAddr =
++ sessionInfo->channelPtr->getRemoteAddressInbytes();
++ response->remotePort =
++ sessionInfo->channelPtr->getPort(); // remoteSessionPort;
++
++ std::cerr << "\nSessionInfo:" << (int)reqSessionID;
++ // TODO: Filling the Remote MACAddress
++ }
++ else
++ {
++ outPayload.resize(4);
++ }
++ return std::move(outPayload);
++}
++
+ } // namespace command
+Index: phosphor-net-ipmid.clean/command/session_cmds.hpp
+===================================================================
+--- phosphor-net-ipmid.clean.orig/command/session_cmds.hpp
++++ phosphor-net-ipmid.clean/command/session_cmds.hpp
+@@ -116,4 +116,59 @@ struct CloseSessionResponse
+ std::vector<uint8_t> closeSession(const std::vector<uint8_t>& inPayload,
+ const message::Handler& handler);
+
++/**
++ * @struct GetSessionInfoRequest
++ *
++ * IPMI Request data for getSession info command
++ */
++struct GetSessionInfoRequest
++{
++ uint8_t sessionIndex;
++ union
++ {
++ uint8_t sessionHandle;
++ uint32_t sessionID;
++ };
++} __attribute__((packed));
++
++/**
++ * @struct getSessionInfoResponse
++ *
++ * IPMI Response data for getSession info command
++ */
++struct GetSessionInfoResponse
++{
++ uint8_t completionCode;
++ uint8_t sessionHandle;
++ uint8_t totalSessionCount;
++ uint8_t activeSessioncount;
++ uint8_t userID;
++ uint8_t privLevel;
++#if BYTE_ORDER == LITTLE_ENDIAN
++ uint8_t chanNum : 4;
++ uint8_t ipmiVer : 4;
++#endif
++#if BYTE_ORDER == BIG_ENDIAN
++ uint8_t ipmiVer : 4;
++ uint8_t chanNum : 4;
++#endif
++ uint32_t remoteIpAddr; // for channel private data
++ uint8_t remoteMACAddr[6];
++ uint16_t remotePort;
++} __attribute__((packed));
++
++/**
++ * @brief GetSessionInfo Command
++ *
++ * This command is used to get the session information based on
++ * session handle or session ID. Retreive all session information.
++
++ * @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> getSessionInfo(const std::vector<uint8_t>& inPayload,
++ const message::Handler& handler);
++
+ } // namespace command
+Index: phosphor-net-ipmid.clean/message_handler.cpp
+===================================================================
+--- phosphor-net-ipmid.clean.orig/message_handler.cpp
++++ phosphor-net-ipmid.clean/message_handler.cpp
+@@ -43,6 +43,7 @@ std::shared_ptr<Message> Handler::receiv
+ sessionID = message->bmcSessionID;
+ message->rcSessionID = session->getRCSessionID();
+ session->updateLastTransactionTime();
++ session->channelPtr = channel;
+
+ return message;
+ }
+Index: phosphor-net-ipmid.clean/sessions_manager.cpp
+===================================================================
+--- phosphor-net-ipmid.clean.orig/sessions_manager.cpp
++++ phosphor-net-ipmid.clean/sessions_manager.cpp
+@@ -88,6 +88,9 @@ std::shared_ptr<Session>
+ }
+ sessionID = session->getBMCSessionID();
+ sessionsMap.emplace(sessionID, session);
++ storeSessionHandle(sessionID);
++
++
+ return session;
+ }
+
+@@ -149,12 +152,15 @@ std::shared_ptr<Session> Manager::getSes
+
+ void Manager::cleanStaleEntries()
+ {
++ uint8_t sessionIndex = 0;
+ for (auto iter = sessionsMap.begin(); iter != sessionsMap.end();)
+ {
+ auto session = iter->second;
+ if ((session->getBMCSessionID() != SESSION_ZERO) &&
+ !(session->isSessionActive()))
+ {
++ sessionIndex = getSessionHandle(session->getBMCSessionID());
++ sessionHandleMap[sessionIndex] = 0;
+ iter = sessionsMap.erase(iter);
+ }
+ else
+@@ -164,4 +170,53 @@ void Manager::cleanStaleEntries()
+ }
+ }
+
++uint8_t Manager::storeSessionHandle(SessionID bmcSessionID)
++{
++ // Zero handler is reserved for invalid session.
++ //index starts with 1, for direct usage. Index 0 reserved
++ for (uint8_t i = 1; i <= MAX_SESSION_COUNT; i++)
++ {
++ if (sessionHandleMap[i] == 0)
++ {
++ sessionHandleMap[i] = bmcSessionID;
++ break;
++ }
++ }
++ return 0;
++}
++
++uint32_t Manager::getSessionIDbyHandle(uint8_t sessionHandle) const
++{
++ if (sessionHandle <= MAX_SESSION_COUNT)
++ {
++ return sessionHandleMap[sessionHandle];
++ }
++ return 0;
++}
++
++uint8_t Manager::getSessionHandle(SessionID bmcSessionID) const
++{
++
++ for (uint8_t i = 1; i <= MAX_SESSION_COUNT; i++)
++ {
++ if (sessionHandleMap[i] == bmcSessionID)
++ {
++ return i;
++ }
++ }
++ return 0;
++}
++uint8_t Manager::getNoOfActiveSession() const
++{
++ uint8_t count = 0;
++ for (const auto& it : sessionsMap)
++ {
++ const auto& session = it.second;
++ if (session->state == State::ACTIVE)
++ {
++ count++;
++ }
++ }
++ return count;
++}
+ } // namespace session
+Index: phosphor-net-ipmid.clean/sessions_manager.hpp
+===================================================================
+--- phosphor-net-ipmid.clean.orig/sessions_manager.hpp
++++ phosphor-net-ipmid.clean/sessions_manager.hpp
+@@ -82,8 +82,15 @@ class Manager
+ std::shared_ptr<Session>
+ getSession(SessionID sessionID,
+ RetrieveOption option = RetrieveOption::BMC_SESSION_ID);
++ uint8_t getNoOfActiveSession() const;
++ uint8_t getSessionHandle(SessionID bmcSessionID) const;
++ uint8_t storeSessionHandle(SessionID bmcSessionID);
++ uint32_t getSessionIDbyHandle(uint8_t sessionHandle) const;
+
+ private:
++ //+1 for session, as 0 is reserved for sessionless command
++ std::array<uint32_t, MAX_SESSION_COUNT + 1> sessionHandleMap;
++
+ /**
+ * @brief Session Manager keeps the session objects as a sorted
+ * associative container with Session ID as the unique key
+Index: phosphor-net-ipmid.clean/socket_channel.hpp
+===================================================================
+--- phosphor-net-ipmid.clean.orig/socket_channel.hpp
++++ phosphor-net-ipmid.clean/socket_channel.hpp
+@@ -65,6 +65,23 @@ class Channel
+ }
+
+ /**
++ * @brief Return the binary representation of the remote IPv4 address
++ *
++ * getSessionInfo needs to return the remote IPv4 addresses of each session
++ *
++ * @return A uint32_t representation of the remote IPv4 address
++ */
++ std::uint32_t getRemoteAddressInbytes()
++ {
++ const boost::asio::ip::address& addr = endpoint.address();
++ if (addr.is_v4())
++ {
++ return addr.to_v4().to_uint();
++ }
++ return 0;
++ }
++
++ /**
+ * @brief Read the incoming packet
+ *
+ * Reads the data available on the socket
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-net/0008-Sync-GetSession-Info-cmd-based-on-Upstream-review.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-net/0008-Sync-GetSession-Info-cmd-based-on-Upstream-review.patch
new file mode 100644
index 000000000..1a109a571
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-net/0008-Sync-GetSession-Info-cmd-based-on-Upstream-review.patch
@@ -0,0 +1,318 @@
+From 0ecc7c816ad4836f8f54922ba92cb527f5978d5a Mon Sep 17 00:00:00 2001
+From: Suryakanth Sekar <suryakanth.sekar@linux.intel.com>
+Date: Wed, 6 Mar 2019 10:35:56 +0530
+Subject: [PATCH] Sync GetSession Info cmd based on Upstream review
+
+Signed-off-by: Suryakanth Sekar <suryakanth.sekar@linux.intel.com>
+---
+ comm_module.cpp | 12 ++++----
+ command/session_cmds.cpp | 72 +++++++++++++++++++++---------------------------
+ sessions_manager.cpp | 10 +++----
+ sessions_manager.hpp | 2 +-
+ socket_channel.hpp | 33 +++++++++++-----------
+ 5 files changed, 59 insertions(+), 70 deletions(-)
+
+diff --git a/comm_module.cpp b/comm_module.cpp
+index 7a1a17d..2546583 100644
+--- a/comm_module.cpp
++++ b/comm_module.cpp
+@@ -54,13 +54,11 @@ void sessionSetupCommands()
+ session::Privilege::CALLBACK,
+ false},
+ // Session Info Command
+- {
+- {
+- (static_cast<uint32_t>(message::PayloadType::IPMI) << 16) |
+- static_cast<uint16_t>(command::NetFns::APP) | 0x3D
+- },
+- &getSessionInfo, session::Privilege::USER, false
+- },
++ {{(static_cast<uint32_t>(message::PayloadType::IPMI) << 16) |
++ static_cast<uint16_t>(command::NetFns::APP) | 0x3D},
++ &getSessionInfo,
++ session::Privilege::USER,
++ false},
+ };
+
+ for (auto& iter : commands)
+diff --git a/command/session_cmds.cpp b/command/session_cmds.cpp
+index 7563b18..fc996a4 100644
+--- a/command/session_cmds.cpp
++++ b/command/session_cmds.cpp
+@@ -5,13 +5,12 @@
+
+ #include <ipmid/api.h>
+
+-#include <iostream>
+ #include <user_channel/channel_layer.hpp>
+ #include <user_channel/user_layer.hpp>
+
+ namespace command
+ {
+-// Defined as per IPMI sepcification
++// Defined as per IPMI specification
+ static constexpr uint8_t searchCurrentSession = 0x00;
+ static constexpr uint8_t searchSessionByHandle = 0xFE;
+ static constexpr uint8_t searchSessionByID = 0xFF;
+@@ -129,20 +128,6 @@ std::vector<uint8_t> getSessionInfo(const std::vector<uint8_t>& inPayload,
+ reinterpret_cast<GetSessionInfoResponse*>(outPayload.data());
+ uint32_t reqSessionID = handler.sessionID;
+ response->completionCode = IPMI_CC_OK;
+- if (inPayload.size() == 1 && request->sessionIndex != 0)
+- {
+- if (request->sessionIndex <= session::MAX_SESSION_COUNT)
+- {
+- reqSessionID = std::get<session::Manager&>(singletonPool)
+- .getSessionIDbyHandle(request->sessionIndex);
+- }
+- else
+- {
+- response->completionCode = IPMI_CC_INVALID_FIELD_REQUEST;
+- outPayload.resize(sizeof(response->completionCode));
+- return std::move(outPayload);
+- }
+- }
+
+ // Here we look for session info according to session index parameter
+ switch (request->sessionIndex)
+@@ -150,29 +135,22 @@ std::vector<uint8_t> getSessionInfo(const std::vector<uint8_t>& inPayload,
+ // Look for current active session which this cmd is received over
+ case searchCurrentSession:
+ // Request data should only contain session index byte
+- if (inPayload.size() != 1)
++ if (inPayload.size() != sizeof(request->sessionIndex))
+ {
+ response->completionCode = IPMI_CC_REQ_DATA_LEN_INVALID;
+ outPayload.resize(sizeof(response->completionCode));
+- return std::move(outPayload);
+- }
+- // To look for current active session which the command came over,
+- // the session ID cannot be 0.
+- if (0 == reqSessionID)
+- {
+- response->completionCode = IPMI_CC_INVALID_FIELD_REQUEST;
+- outPayload.resize(sizeof(response->completionCode));
+- return std::move(outPayload);
++ return outPayload;
+ }
+ break;
+ case searchSessionByHandle:
+ // Request data should only contain session index byte and Session
+ // handle
+- if (inPayload.size() != 2)
++ if (inPayload.size() != (sizeof(request->sessionIndex) +
++ sizeof(request->sessionHandle)))
+ {
+ response->completionCode = IPMI_CC_REQ_DATA_LEN_INVALID;
+ outPayload.resize(sizeof(response->completionCode));
+- return std::move(outPayload);
++ return outPayload;
+ }
+
+ // Retrieve session id based on session handle
+@@ -186,7 +164,7 @@ std::vector<uint8_t> getSessionInfo(const std::vector<uint8_t>& inPayload,
+ {
+ response->completionCode = IPMI_CC_INVALID_FIELD_REQUEST;
+ outPayload.resize(sizeof(response->completionCode));
+- return std::move(outPayload);
++ return outPayload;
+ }
+ break;
+ case searchSessionByID:
+@@ -196,23 +174,38 @@ std::vector<uint8_t> getSessionInfo(const std::vector<uint8_t>& inPayload,
+ {
+ response->completionCode = IPMI_CC_REQ_DATA_LEN_INVALID;
+ outPayload.resize(sizeof(response->completionCode));
+- return std::move(outPayload);
++ return outPayload;
+ }
+ reqSessionID = endian::from_ipmi(request->sessionID);
+
+ break;
+ default:
+- if (inPayload.size() != 1)
++ if (inPayload.size() == sizeof(request->sessionIndex))
++ {
++ if (request->sessionIndex <= session::MAX_SESSION_COUNT)
++ {
++ reqSessionID =
++ std::get<session::Manager&>(singletonPool)
++ .getSessionIDbyHandle(request->sessionIndex);
++ }
++ else
++ {
++ response->completionCode = IPMI_CC_REQ_DATA_LEN_INVALID;
++ outPayload.resize(sizeof(response->completionCode));
++ return outPayload;
++ }
++ }
++ else
+ {
+ response->completionCode = IPMI_CC_REQ_DATA_LEN_INVALID;
+ outPayload.resize(sizeof(response->completionCode));
+- return std::move(outPayload);
++ return outPayload;
+ }
+ }
+
+ response->totalSessionCount = session::MAX_SESSION_COUNT;
+ response->activeSessioncount =
+- std::get<session::Manager&>(singletonPool).getNoOfActiveSession();
++ std::get<session::Manager&>(singletonPool).getActiveSessionCount();
+ response->sessionHandle = 0;
+ if (reqSessionID != 0)
+ {
+@@ -225,9 +218,9 @@ std::vector<uint8_t> getSessionInfo(const std::vector<uint8_t>& inPayload,
+ }
+ catch (std::exception& e)
+ {
+- response->completionCode = IPMI_CC_UNSPECIFIED_ERROR;
++ response->completionCode = IPMI_CC_REQ_DATA_LEN_INVALID;
+ outPayload.resize(sizeof(response->completionCode));
+- return std::move(outPayload);
++ return outPayload;
+ }
+ response->sessionHandle = std::get<session::Manager&>(singletonPool)
+ .getSessionHandle(reqSessionID);
+@@ -236,25 +229,24 @@ std::vector<uint8_t> getSessionInfo(const std::vector<uint8_t>& inPayload,
+ {
+ response->completionCode = IPMI_CC_UNSPECIFIED_ERROR;
+ outPayload.resize(sizeof(response->completionCode));
+- return std::move(outPayload);
++ return outPayload;
+ }
+ response->userID = userId; // userId;
+ response->privLevel = static_cast<uint8_t>(sessionInfo->curPrivLevel);
+ response->chanNum = sessionInfo->chNum; // byte7 3:0
+ response->ipmiVer = ipmi20VerSession; // byte7 7:4
+- response->remoteIpAddr =
+- sessionInfo->channelPtr->getRemoteAddressInbytes();
+ response->remotePort =
+ sessionInfo->channelPtr->getPort(); // remoteSessionPort;
++ response->remoteIpAddr =
++ sessionInfo->channelPtr->getRemoteAddressInBytes();
+
+- std::cerr << "\nSessionInfo:" << (int)reqSessionID;
+ // TODO: Filling the Remote MACAddress
+ }
+ else
+ {
+ outPayload.resize(4);
+ }
+- return std::move(outPayload);
++ return outPayload;
+ }
+
+ } // namespace command
+diff --git a/sessions_manager.cpp b/sessions_manager.cpp
+index 9f3210b..c6897c6 100644
+--- a/sessions_manager.cpp
++++ b/sessions_manager.cpp
+@@ -152,15 +152,13 @@ std::shared_ptr<Session> Manager::getSession(SessionID sessionID,
+
+ void Manager::cleanStaleEntries()
+ {
+- uint8_t sessionIndex = 0;
+ for (auto iter = sessionsMap.begin(); iter != sessionsMap.end();)
+ {
+ auto session = iter->second;
+ if ((session->getBMCSessionID() != SESSION_ZERO) &&
+ !(session->isSessionActive()))
+ {
+- sessionIndex = getSessionHandle(session->getBMCSessionID());
+- sessionHandleMap[sessionIndex] = 0;
++ sessionHandleMap[getSessionHandle(session->getBMCSessionID())] = 0;
+ iter = sessionsMap.erase(iter);
+ }
+ else
+@@ -172,8 +170,8 @@ void Manager::cleanStaleEntries()
+
+ uint8_t Manager::storeSessionHandle(SessionID bmcSessionID)
+ {
+- // Zero handler is reserved for invalid session.
+- //index starts with 1, for direct usage. Index 0 reserved
++ // Handler index 0 is reserved for invalid session.
++ // index starts with 1, for direct usage. Index 0 reserved
+ for (uint8_t i = 1; i <= MAX_SESSION_COUNT; i++)
+ {
+ if (sessionHandleMap[i] == 0)
+@@ -206,7 +204,7 @@ uint8_t Manager::getSessionHandle(SessionID bmcSessionID) const
+ }
+ return 0;
+ }
+-uint8_t Manager::getNoOfActiveSession() const
++uint8_t Manager::getActiveSessionCount() const
+ {
+ uint8_t count = 0;
+ for (const auto& it : sessionsMap)
+diff --git a/sessions_manager.hpp b/sessions_manager.hpp
+index c4caad4..3a3825d 100644
+--- a/sessions_manager.hpp
++++ b/sessions_manager.hpp
+@@ -82,7 +82,7 @@ class Manager
+ std::shared_ptr<Session>
+ getSession(SessionID sessionID,
+ RetrieveOption option = RetrieveOption::BMC_SESSION_ID);
+- uint8_t getNoOfActiveSession() const;
++ uint8_t getActiveSessionCount() const;
+ uint8_t getSessionHandle(SessionID bmcSessionID) const;
+ uint8_t storeSessionHandle(SessionID bmcSessionID);
+ uint32_t getSessionIDbyHandle(uint8_t sessionHandle) const;
+diff --git a/socket_channel.hpp b/socket_channel.hpp
+index 349701e..8b64740 100644
+--- a/socket_channel.hpp
++++ b/socket_channel.hpp
+@@ -52,33 +52,34 @@ class Channel
+ }
+
+ /**
+- * @brief Fetch the port number of the remote peer
+- *
+- * Returns the port number of the remote peer
++ * @brief Fetch the IP address of the remote peer
+ *
+- * @return Port number
++ * Returns the IP address of the remote peer which is connected to this
++ * socket
+ *
++ * @return IP address of the remote peer
+ */
+- auto getPort() const
++ std::uint32_t getRemoteAddressInBytes() const
+ {
+- return endpoint.port();
++ const boost::asio::ip::address& addr = endpoint.address();
++ if (addr.is_v4())
++ {
++ return addr.to_v4().to_uint();
++ }
++ return 0;
+ }
+
+ /**
+- * @brief Return the binary representation of the remote IPv4 address
++ * @brief Fetch the port number of the remote peer
+ *
+- * getSessionInfo needs to return the remote IPv4 addresses of each session
++ * Returns the port number of the remote peer
++ *
++ * @return Port number
+ *
+- * @return A uint32_t representation of the remote IPv4 address
+ */
+- std::uint32_t getRemoteAddressInbytes()
++ auto getPort() const
+ {
+- const boost::asio::ip::address& addr = endpoint.address();
+- if (addr.is_v4())
+- {
+- return addr.to_v4().to_uint();
+- }
+- return 0;
++ return endpoint.port();
+ }
+
+ /**
+--
+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..19fa4c06b
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-net_%.bbappend
@@ -0,0 +1,13 @@
+inherit useradd
+
+USERADD_PACKAGES = "${PN}"
+# add a group called ipmi
+GROUPADD_PARAM_${PN} = "ipmi "
+
+FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
+
+SRC_URI += " file://0006-Modify-dbus-namespace-of-chassis-control-for-guid.patch \
+ file://0007-Adding-support-for-GetSessionInfo-command.patch \
+ file://0008-Sync-GetSession-Info-cmd-based-on-Upstream-review.patch \
+ "
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-node-manager-proxy_git.bb b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-node-manager-proxy_git.bb
new file mode 100644
index 000000000..24b1dd2a0
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-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/openbmc-intel/node-manager;protocol=ssh"
+SRCREV = "596cd421d4749c8b6d672fb410eccf9f2da08b3a"
+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
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..808cee1ed
--- /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-amr-2.devtools.intel.com:29418/openbmc-node-manager;protocol=ssh"
+SRCREV = "e5a5f6189ce357438f40116717b995bab82c50ae"
+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
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/leds/intel-led-manager-config-native.bb b/meta-openbmc-mods/meta-common/recipes-phosphor/leds/intel-led-manager-config-native.bb
new file mode 100644
index 000000000..dd48df0c6
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/leds/intel-led-manager-config-native.bb
@@ -0,0 +1,21 @@
+SUMMARY = "Phosphor LED Group Management for Intel"
+PR = "r1"
+
+inherit native
+inherit obmc-phosphor-utils
+
+LICENSE = "Apache-2.0"
+LIC_FILES_CHKSUM = "file://${INTELBASE}/COPYING.apache-2.0;md5=34400b68072d710fecd0a2940a0d1658"
+
+PROVIDES += "virtual/phosphor-led-manager-config-native"
+
+SRC_URI += "file://led.yaml"
+S = "${WORKDIR}"
+
+# Overwrite the example led layout yaml file prior
+# to building the phosphor-led-manager package
+do_install() {
+ SRC=${S}
+ DEST=${D}${datadir}/phosphor-led-manager
+ install -D ${SRC}/led.yaml ${DEST}/led.yaml
+}
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/leds/intel-led-manager-config/led.yaml b/meta-openbmc-mods/meta-common/recipes-phosphor/leds/intel-led-manager-config/led.yaml
new file mode 100755
index 000000000..813ffbfd4
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/leds/intel-led-manager-config/led.yaml
@@ -0,0 +1,36 @@
+bmc_booted:
+
+power_on:
+
+status_ok:
+ status_green:
+ Action: 'On'
+ status_amber:
+ Action: 'Off'
+
+status_degraded:
+ status_green:
+ Action: 'Blink'
+ DutyOn: 50
+ Period: 1000
+ status_amber:
+ Action: 'Off'
+
+status_non_critical:
+ status_green:
+ Action: 'Off'
+ status_amber:
+ Action: 'Blink'
+ DutyOn: 50
+ Period: 1000
+
+status_critical:
+ status_green:
+ Action: 'Off'
+ status_amber:
+ Action: 'On'
+
+enclosure_identify:
+ identify:
+ Action: 'On'
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/logging/phosphor-logging_%.bbappend b/meta-openbmc-mods/meta-common/recipes-phosphor/logging/phosphor-logging_%.bbappend
new file mode 100644
index 000000000..b1f4c1ce5
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/logging/phosphor-logging_%.bbappend
@@ -0,0 +1,2 @@
+SRCREV = "30047bf9647215951ba5dfe21ceb3e58a1b405a4"
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/sel-logger/phosphor-sel-logger_%.bbappend b/meta-openbmc-mods/meta-common/recipes-phosphor/sel-logger/phosphor-sel-logger_%.bbappend
new file mode 100644
index 000000000..809d05b94
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/sel-logger/phosphor-sel-logger_%.bbappend
@@ -0,0 +1,6 @@
+# Enable downstream autobump
+SRC_URI = "git://github.com/openbmc/phosphor-sel-logger.git"
+SRCREV = "2b9704d7eb666c945c73dd74a426a0af2292b0ea"
+
+# Enable threshold monitoring
+EXTRA_OECMAKE += "-DSEL_LOGGER_MONITOR_THRESHOLD_EVENTS=ON"
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/selftest/intel-self-test/xyz.openbmc_project.selftest.service b/meta-openbmc-mods/meta-common/recipes-phosphor/selftest/intel-self-test/xyz.openbmc_project.selftest.service
new file mode 100644
index 000000000..b8c3554ae
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/selftest/intel-self-test/xyz.openbmc_project.selftest.service
@@ -0,0 +1,10 @@
+[Unit]
+Description= BMC Self-Test
+
+[Service]
+Restart=always
+ExecStart=/usr/bin/env selftest
+SyslogIdentifier=selftest
+
+[Install]
+WantedBy=multi-user.target
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/selftest/intel-self-test_git.bb b/meta-openbmc-mods/meta-common/recipes-phosphor/selftest/intel-self-test_git.bb
new file mode 100644
index 000000000..da1d74207
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/selftest/intel-self-test_git.bb
@@ -0,0 +1,38 @@
+SUMMARY = "BMC Self Test service"
+DESCRIPTION = "BMC Self Test service for subsystem diagnosis failure info"
+
+SRC_URI = "git://git@github.com/Intel-BMC/intel-self-test;protocol=ssh"
+
+PV = "1.0+git${SRCPV}"
+SRCREV = "d039998ad2c55aeae4191af30e15bbd3032508c1"
+
+S = "${WORKDIR}/git"
+
+LICENSE = "Apache-2.0"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=fa818a259cbed7ce8bc2a22d35a464fc"
+
+inherit cmake
+inherit obmc-phosphor-dbus-service
+inherit obmc-phosphor-systemd
+inherit pkgconfig pythonnative
+
+SYSTEMD_SERVICE_${PN} += "xyz.openbmc_project.selftest.service"
+
+DEPENDS += " \
+ autoconf-archive-native \
+ systemd \
+ sdbusplus \
+ sdbusplus-native \
+ phosphor-logging \
+ phosphor-dbus-interfaces \
+ phosphor-dbus-interfaces-native \
+ "
+
+RDEPENDS_${PN} += " \
+ libsystemd \
+ sdbusplus \
+ phosphor-logging \
+ phosphor-dbus-interfaces \
+ "
+
+EXTRA_OECMAKE = " -DENABLE_GTEST=OFF -DCMAKE_SKIP_RPATH=ON"
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/sensors/dbus-sensors_%.bbappend b/meta-openbmc-mods/meta-common/recipes-phosphor/sensors/dbus-sensors_%.bbappend
new file mode 100644
index 000000000..56fb8531d
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/sensors/dbus-sensors_%.bbappend
@@ -0,0 +1,8 @@
+SRCREV = "46342ec359c8e0ed543ebb352cfba8f26ce85afe"
+SRC_URI = "git://github.com/openbmc/dbus-sensors.git"
+
+DEPENDS_append = " i2c-tools"
+
+# turn this back on when we have a need, but disable it now
+# as no shipping platforms use it and it will take cpu cycles
+EXTRA_OECMAKE_append = " -DDISABLE_INTRUSION=ON"
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/settings/phosphor-settings-defaults-native.bbappend b/meta-openbmc-mods/meta-common/recipes-phosphor/settings/phosphor-settings-defaults-native.bbappend
new file mode 100644
index 000000000..436623234
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/settings/phosphor-settings-defaults-native.bbappend
@@ -0,0 +1,4 @@
+FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
+
+SRC_URI += "file://defaults.yaml \
+ "
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/settings/phosphor-settings-defaults-native/defaults.yaml b/meta-openbmc-mods/meta-common/recipes-phosphor/settings/phosphor-settings-defaults-native/defaults.yaml
new file mode 100644
index 000000000..24816fb4c
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/settings/phosphor-settings-defaults-native/defaults.yaml
@@ -0,0 +1,181 @@
+/xyz/openbmc_project/control/minimum_ship_level_required:
+ - Interface: xyz.openbmc_project.Control.MinimumShipLevel
+ Properties:
+ MinimumShipLevelRequired:
+ Default: 'true'
+
+/xyz/openbmc_project/control/host0/auto_reboot:
+ - Interface: xyz.openbmc_project.Control.Boot.RebootPolicy
+ Properties:
+ AutoReboot:
+ Default: 'false'
+
+/xyz/openbmc_project/control/host0/boot:
+ - Interface: xyz.openbmc_project.Control.Boot.Source
+ Properties:
+ BootSource:
+ Default: Source::Sources::Default
+ - Interface: xyz.openbmc_project.Control.Boot.Mode
+ Properties:
+ BootMode:
+ Default: Mode::Modes::Regular
+
+/xyz/openbmc_project/control/host0/boot/one_time:
+ - Interface: xyz.openbmc_project.Control.Boot.Source
+ Properties:
+ BootSource:
+ Default: Source::Sources::Default
+ - Interface: xyz.openbmc_project.Control.Boot.Mode
+ Properties:
+ BootMode:
+ Default: Mode::Modes::Regular
+ - Interface: xyz.openbmc_project.Object.Enable
+ Properties:
+ Enabled:
+ Default: 'true'
+
+/xyz/openbmc_project/control/host0/power_cap:
+ - Interface: xyz.openbmc_project.Control.Power.Cap
+ Properties:
+ PowerCap:
+ Default: 0
+ Validation:
+ Type: "range"
+ Validator: "0..1000"
+ Unit: "Watts"
+ PowerCapEnable:
+ Default: 'false'
+
+/xyz/openbmc_project/control/host0/power_restore_policy:
+ - Interface: xyz.openbmc_project.Control.Power.RestorePolicy
+ Properties:
+ PowerRestorePolicy:
+ Default: RestorePolicy::Policy::AlwaysOff
+
+/xyz/openbmc_project/control/power_restore_delay:
+ - Interface: xyz.openbmc_project.Control.Power.RestoreDelay
+ Properties:
+ PowerRestoreDelay:
+ Default: 0
+
+/xyz/openbmc_project/control/host0/acpi_power_state:
+ - Interface: xyz.openbmc_project.Control.Power.ACPIPowerState
+ Properties:
+ SysACPIStatus:
+ Default: ACPIPowerState::ACPI::Unknown
+ DevACPIStatus:
+ Default: ACPIPowerState::ACPI::Unknown
+
+/xyz/openbmc_project/time/owner:
+ - Interface: xyz.openbmc_project.Time.Owner
+ Properties:
+ TimeOwner:
+ Default: Owner::Owners::BMC
+
+/xyz/openbmc_project/time/sync_method:
+ - Interface: xyz.openbmc_project.Time.Synchronization
+ Properties:
+ TimeSyncMethod:
+ Default: Synchronization::Method::NTP
+
+/xyz/openbmc_project/network/host0/intf:
+ - Interface: xyz.openbmc_project.Network.MACAddress
+ Properties:
+ MACAddress:
+ Default: '"00:00:00:00:00:00"'
+ Validation:
+ Type: "regex"
+ Validator: '^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$'
+
+#needs to implement address validation TODO openbmc/issues/2046
+/xyz/openbmc_project/network/host0/intf/addr:
+ - Interface: xyz.openbmc_project.Network.IP
+ Properties:
+ Address:
+ Default: '"0.0.0.0"'
+ PrefixLength:
+ Default: 0
+ Validation:
+ Type: "range"
+ Validator: 0..128
+ Unit: "bits"
+ Origin:
+ Default: IP::AddressOrigin::Static
+ Gateway:
+ Default: '"0.0.0.0"'
+ Type:
+ Default: IP::Protocol::IPv4
+
+/xyz/openbmc_project/control/host0/restriction_mode:
+ - Interface: xyz.openbmc_project.Control.Security.RestrictionMode
+ Properties:
+ RestrictionMode:
+ Default: RestrictionMode::Modes::None
+
+/xyz/openbmc_project/control/host0/TPMEnable:
+ - Interface: xyz.openbmc_project.Control.TPM.Policy
+ Properties:
+ TPMEnable:
+ Default: 'false'
+
+/xyz/openbmc_project/control/power_supply_redundancy:
+ - Interface: xyz.openbmc_project.Control.PowerSupplyRedundancy
+ Properties:
+ PowerSupplyRedundancyEnabled:
+ Default: 'true'
+
+/xyz/openbmc_project/control/host0/turbo_allowed:
+ - Interface: xyz.openbmc_project.Control.Host.TurboAllowed
+ Properties:
+ TurboAllowed:
+ Default: 'true'
+
+/xyz/openbmc_project/control/host0/systemGUID:
+ - Interface: xyz.openbmc_project.Common.UUID
+ Properties:
+ UUID:
+ Default: '"00000000-0000-0000-0000-000000000000"'
+
+/xyz/openbmc_project/bios:
+ - Interface: xyz.openbmc_project.Inventory.Item.Bios
+ Properties:
+ BiosId:
+ Default: '"NA"'
+
+/xyz/openbmc_project/control/processor_error_config:
+ - Interface: xyz.openbmc_project.Control.Processor.ErrConfig
+ Properties:
+ ResetCfg:
+ Default: 0
+ ResetErrorOccurrenceCounts:
+ Default: 0
+
+/xyz/openbmc_project/control/shutdown_policy_config:
+ - Interface: xyz.openbmc_project.Control.ShutdownPolicy
+ Properties:
+ Policy:
+ Default: 0
+
+/xyz/openbmc_project/control/chassis_capabilities_config:
+ - Interface: xyz.openbmc_project.Control.ChassisCapabilities
+ Properties:
+ CapabilitiesFlags:
+ Default: 0
+ FRUDeviceAddress:
+ Default: 0x20
+ SDRDeviceAddress:
+ Default: 0x20
+ SELDeviceAddress:
+ Default: 0x20
+ SMDeviceAddress:
+ Default: 0x20
+ BridgeDeviceAddress:
+ Default: 0x20
+
+/xyz/openbmc_project/control/thermal_mode:
+ - Interface: xyz.openbmc_project.Control.ThermalMode
+ Properties:
+ Current:
+ Default: '"Performance"'
+ Supported:
+ Default: '{"Acoustic", "Performance"}'
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/settings/phosphor-settings-manager/0001-settings-initialize-data-file-with-default-setting.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/settings/phosphor-settings-manager/0001-settings-initialize-data-file-with-default-setting.patch
new file mode 100644
index 000000000..fcf2415d6
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/settings/phosphor-settings-manager/0001-settings-initialize-data-file-with-default-setting.patch
@@ -0,0 +1,37 @@
+From 9e99aa4f72f4420e03ec2e4a29816eae43c5e748 Mon Sep 17 00:00:00 2001
+From: "Jia, Chunhui" <chunhui.jia@intel.com>
+Date: Tue, 29 May 2018 16:16:06 +0800
+Subject: [PATCH] [settings] initialize data file with default setting
+
+Current code trys to load settings from file at startup. When file
+does not exist, it will just use default setting. However, it will
+still load default on next reboot because no one create files.
+
+This change creates file as well when daemon loads default so next
+time daemon could load/save from file.
+
+Signed-off-by: Jia, Chunhui <chunhui.jia@intel.com>
+---
+ settings_manager.mako.hpp | 3 +++
+ 1 file changed, 3 insertions(+)
+ mode change 100644 => 100755 settings_manager.mako.hpp
+
+diff --git a/settings_manager.mako.hpp b/settings_manager.mako.hpp
+old mode 100644
+new mode 100755
+index 09a5a1f..cd592a0
+--- a/settings_manager.mako.hpp
++++ b/settings_manager.mako.hpp
+@@ -323,6 +323,9 @@ class Manager
+ else
+ {
+ initSetting${index}();
++ std::ofstream ostr(path.c_str(), std::ios::out);
++ cereal::JSONOutputArchive oarchive(ostr);
++ oarchive(*std::get<${index}>(settings)); //create file with default
+ }
+ }
+ catch (cereal::Exception& e)
+--
+2.16.2
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/settings/phosphor-settings-manager_%.bbappend b/meta-openbmc-mods/meta-common/recipes-phosphor/settings/phosphor-settings-manager_%.bbappend
new file mode 100644
index 000000000..bc695abe8
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/settings/phosphor-settings-manager_%.bbappend
@@ -0,0 +1,4 @@
+FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
+
+SRC_URI += "file://0001-settings-initialize-data-file-with-default-setting.patch \
+ "
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/srvcfg-manager/srvcfg-manager_git.bb b/meta-openbmc-mods/meta-common/recipes-phosphor/srvcfg-manager/srvcfg-manager_git.bb
new file mode 100644
index 000000000..184b539a9
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/srvcfg-manager/srvcfg-manager_git.bb
@@ -0,0 +1,28 @@
+SUMMARY = "Service configuration manager daemon to control service properties"
+DESCRIPTION = "Daemon controls service properies like port, channels, state etc.."
+
+PV = "1.0+git${SRCPV}"
+
+S = "${WORKDIR}/git/srvcfg-manager"
+
+LICENSE = "Apache-2.0"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=e3fc50a88d0a364313df4b21ef20c29e"
+
+SRC_URI = "git://git@github.com/Intel-BMC/provingground.git;protocol=ssh"
+SRCREV = "3cc86d6c536b4c5ee7afb5447837b83ce8b3d149"
+
+inherit cmake systemd
+SYSTEMD_SERVICE_${PN} = "srvcfg-manager.service"
+
+DEPENDS += " \
+ systemd \
+ sdbusplus \
+ sdbusplus-native \
+ phosphor-logging \
+ boost \
+ "
+RDEPENDS_${PN} += " \
+ libsystemd \
+ sdbusplus \
+ phosphor-logging \
+ "
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/state/phosphor-state-manager/0001-Modify-dbus-interface-for-power-control.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/state/phosphor-state-manager/0001-Modify-dbus-interface-for-power-control.patch
new file mode 100644
index 000000000..fac9b52f1
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/state/phosphor-state-manager/0001-Modify-dbus-interface-for-power-control.patch
@@ -0,0 +1,38 @@
+From d34a2a5f6ca0564275ed0e2664624525cad64585 Mon Sep 17 00:00:00 2001
+From: Yong Li <yong.b.li@linux.intel.com>
+Date: Fri, 13 Jul 2018 09:08:52 +0800
+Subject: [PATCH] Modify dbus interface for power control
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Switch power control service namespace from “org” to “xyz”,
+to compatible with new intel-chassis services
+
+Change-Id: I1bf5e218f72eb9fd4fb6f203c35479818d12b1fa
+Signed-off-by: Yong Li <yong.b.li@linux.intel.com>
+---
+ chassis_state_manager.cpp | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/chassis_state_manager.cpp b/chassis_state_manager.cpp
+index 03dd176..05e2440 100644
+--- a/chassis_state_manager.cpp
++++ b/chassis_state_manager.cpp
+@@ -63,10 +63,11 @@ void Chassis::determineInitialState()
+ {
+ sdbusplus::message::variant<int> pgood = -1;
+ auto method = this->bus.new_method_call(
+- "org.openbmc.control.Power", "/org/openbmc/control/power0",
++ "xyz.openbmc_project.Chassis.Control.Power",
++ "/xyz/openbmc_project/Chassis/Control/Power0",
+ "org.freedesktop.DBus.Properties", "Get");
+
+- method.append("org.openbmc.control.Power", "pgood");
++ method.append("xyz.openbmc_project.Chassis.Control.Power", "pgood");
+ try
+ {
+ auto reply = this->bus.call(method);
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/state/phosphor-state-manager/0002-Capture-host-restart-cause.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/state/phosphor-state-manager/0002-Capture-host-restart-cause.patch
new file mode 100644
index 000000000..7c6f684ca
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/state/phosphor-state-manager/0002-Capture-host-restart-cause.patch
@@ -0,0 +1,192 @@
+From 8dea573181c4455e144335e14cac9f54ebbf7208 Mon Sep 17 00:00:00 2001
+From: Kuiying Wang <kuiying.wang@intel.com>
+Date: Tue, 7 Aug 2018 16:43:00 +0800
+Subject: [PATCH] Capture host restart cause
+
+Capture host restart cause on power/reset button pressed.
+Save the restart cause into file system.
+And restort it when BMC boot up.
+
+Signed-off-by: Kuiying Wang <kuiying.wang@intel.com>
+---
+ configure.ac | 4 +--
+ host_state_manager.cpp | 16 ++++++++++++
+ host_state_manager.hpp | 56 +++++++++++++++++++++++++++++++++++++++---
+ 3 files changed, 71 insertions(+), 5 deletions(-)
+
+diff --git a/configure.ac b/configure.ac
+index 838aaf2..5879e2f 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -54,9 +54,9 @@ AC_ARG_VAR(HOST_RUNNING_FILE, [File to create if host is running])
+ AS_IF([test "x$HOST_RUNNING_FILE" == "x"], [HOST_RUNNING_FILE="/run/openbmc/host@%u-on"])
+ AC_DEFINE_UNQUOTED([HOST_RUNNING_FILE], ["$HOST_RUNNING_FILE"], [File to create if host is running])
+
+-AC_ARG_VAR(HOST_STATE_PERSIST_PATH, [Path of file for storing requested host state.])
++AC_ARG_VAR(HOST_STATE_PERSIST_PATH, [Path of file for storing host state.])
+ AS_IF([test "x$HOST_STATE_PERSIST_PATH" == "x"], \
+- [HOST_STATE_PERSIST_PATH="/var/lib/phosphor-state-manager/requestedHostTransition"])
++ [HOST_STATE_PERSIST_PATH="/var/lib/phosphor-state-manager/hostState"])
+ AC_DEFINE_UNQUOTED([HOST_STATE_PERSIST_PATH], ["$HOST_STATE_PERSIST_PATH"], \
+ [Path of file for storing requested host state.])
+
+diff --git a/host_state_manager.cpp b/host_state_manager.cpp
+index ec1f95f..8573d00 100644
+--- a/host_state_manager.cpp
++++ b/host_state_manager.cpp
+@@ -304,6 +304,15 @@ bool Host::deserialize(const fs::path& path)
+ }
+ }
+
++void Host::restoreHostRestartCause()
++{
++ if (!deserialize(HOST_STATE_PERSIST_PATH))
++ {
++ // set to default value
++ server::Host::hostRestartCause(server::Host::RestartCause::Unknown);
++ }
++}
++
+ Host::Transition Host::requestedHostTransition(Transition value)
+ {
+ log<level::INFO>("Host State transaction request",
+@@ -349,6 +358,13 @@ Host::HostState Host::currentHostState(HostState value)
+ return server::Host::currentHostState(value);
+ }
+
++Host::RestartCause Host::hostRestartCause(RestartCause value)
++{
++ auto retVal = server::Host::hostRestartCause(value);
++ serialize();
++ return retVal;
++}
++
+ } // namespace manager
+ } // namespace state
+ } // namepsace phosphor
+diff --git a/host_state_manager.hpp b/host_state_manager.hpp
+index 2b00777..e74fab7 100644
+--- a/host_state_manager.hpp
++++ b/host_state_manager.hpp
+@@ -32,6 +32,15 @@ using namespace phosphor::logging;
+ namespace sdbusRule = sdbusplus::bus::match::rules;
+ namespace fs = std::experimental::filesystem;
+
++const static constexpr char* powerButtonPath =
++ "/xyz/openbmc_project/Chassis/Buttons/Power0";
++const static constexpr char* powerButtonIntf =
++ "xyz.openbmc_project.Chassis.Buttons.Power";
++const static constexpr char* resetButtonPath =
++ "/xyz/openbmc_project/Chassis/Buttons/Reset0";
++const static constexpr char* resetButtonIntf =
++ "xyz.openbmc_project.Chassis.Buttons.Reset";
++
+ /** @class Host
+ * @brief OpenBMC host state management implementation.
+ * @details A concrete implementation for xyz.openbmc_project.State.Host
+@@ -59,7 +68,31 @@ class Host : public HostInherit
+ sdbusRule::interface("org.freedesktop.systemd1.Manager"),
+ std::bind(std::mem_fn(&Host::sysStateChange), this,
+ std::placeholders::_1)),
+- settings(bus)
++ settings(bus),
++ powerButtonPressedSignal(
++ bus,
++ sdbusRule::type::signal() + sdbusRule::member("Pressed") +
++ sdbusRule::path(powerButtonPath) +
++ sdbusRule::interface(powerButtonIntf),
++ [this](sdbusplus::message::message &msg) {
++ phosphor::logging::log<phosphor::logging::level::INFO>(
++ "powerButtonPressedSignal callback function is called...");
++ this->hostRestartCause(this->RestartCause::PowerButton);
++ return;
++ }
++ ),
++ resetButtonPressedSignal(
++ bus,
++ sdbusRule::type::signal() + sdbusRule::member("Pressed") +
++ sdbusRule::path(resetButtonPath) +
++ sdbusRule::interface(resetButtonIntf),
++ [this](sdbusplus::message::message &msg) {
++ phosphor::logging::log<phosphor::logging::level::INFO>(
++ "resetButtonPressedSignal callback function is called...");
++ this->hostRestartCause(this->RestartCause::ResetButton);
++ return;
++ }
++ )
+ {
+ // Enable systemd signals
+ subscribeToSystemdSignals();
+@@ -69,6 +102,8 @@ class Host : public HostInherit
+
+ attemptsLeft(BOOT_COUNT_MAX_ALLOWED);
+
++ restoreHostRestartCause(); // restore host restart cause from persisted file
++
+ // We deferred this until we could get our property correct
+ this->emit_object_added();
+ }
+@@ -85,6 +120,9 @@ class Host : public HostInherit
+ /** @brief Set value of CurrentHostState */
+ HostState currentHostState(HostState value) override;
+
++ /** @brief Set value of HostRestartCause */
++ RestartCause hostRestartCause(RestartCause value) override;
++
+ /**
+ * @brief Set host reboot count to default
+ *
+@@ -192,7 +230,10 @@ class Host : public HostInherit
+ server::Progress::bootProgress()),
+ convertForMessage(
+ sdbusplus::xyz::openbmc_project::State::OperatingSystem::
+- server::Status::operatingSystemState()));
++ server::Status::operatingSystemState()),
++ convertForMessage(sdbusplus::xyz::openbmc_project::State::
++ server::Host::hostRestartCause())
++ );
+ }
+
+ /** @brief Function required by Cereal to perform deserialization.
+@@ -208,7 +249,8 @@ class Host : public HostInherit
+ std::string reqTranState;
+ std::string bootProgress;
+ std::string osState;
+- archive(reqTranState, bootProgress, osState);
++ std::string restartCause;
++ archive(reqTranState, bootProgress, osState, restartCause);
+ auto reqTran = Host::convertTransitionFromString(reqTranState);
+ // When restoring, set the requested state with persistent value
+ // but don't call the override which would execute it
+@@ -219,6 +261,8 @@ class Host : public HostInherit
+ sdbusplus::xyz::openbmc_project::State::OperatingSystem::server::
+ Status::operatingSystemState(
+ Host::convertOSStatusFromString(osState));
++ sdbusplus::xyz::openbmc_project::State::server::Host::
++ hostRestartCause(Host::convertRestartCauseFromString(restartCause));
+ }
+
+ /** @brief Serialize and persist requested host state
+@@ -239,6 +283,9 @@ class Host : public HostInherit
+ */
+ bool deserialize(const fs::path& path);
+
++ /** @brief Used to restore HostRestartCause value from persisted file */
++ void restoreHostRestartCause();
++
+ /** @brief Persistent sdbusplus DBus bus connection. */
+ sdbusplus::bus::bus& bus;
+
+@@ -247,6 +294,9 @@ class Host : public HostInherit
+
+ // Settings objects of interest
+ settings::Objects settings;
++
++ sdbusplus::bus::match_t powerButtonPressedSignal;
++ sdbusplus::bus::match_t resetButtonPressedSignal;
+ };
+
+ } // namespace manager
+--
+2.17.0
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/state/phosphor-state-manager/phosphor-reboot-host@.service b/meta-openbmc-mods/meta-common/recipes-phosphor/state/phosphor-state-manager/phosphor-reboot-host@.service
new file mode 100644
index 000000000..ffde01ca3
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/state/phosphor-state-manager/phosphor-reboot-host@.service
@@ -0,0 +1,18 @@
+[Unit]
+Description=Reboot host%i
+Wants=obmc-host-stop@%i.target
+After=obmc-host-stop@%i.target
+
+[Service]
+#ExecStart={base_bindir}/systemctl start obmc-host-start@%i.target
+# This service is starting another target that conflicts with the
+# target this service is running in. OpenBMC needs a refactor of
+# how it does its host reset path. Until then, this short term
+# solution does the job.
+# Since this is a part of the reboot target, call the startmin
+# target which does the minimum required to start the host.
+ExecStart=/bin/sh -c "sleep 10 && systemctl start obmc-host-startmin@%i.target"
+
+
+[Install]
+WantedBy=obmc-host-reboot@%i.target
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/state/phosphor-state-manager/phosphor-reset-host-check@.service b/meta-openbmc-mods/meta-common/recipes-phosphor/state/phosphor-state-manager/phosphor-reset-host-check@.service
new file mode 100644
index 000000000..13b8f0fca
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/state/phosphor-state-manager/phosphor-reset-host-check@.service
@@ -0,0 +1,19 @@
+[Unit]
+Description=Check Host%i status on BMC reset
+Wants=mapper-wait@-xyz-openbmc_project-control-host%i.service
+After=mapper-wait@-xyz-openbmc_project-control-host%i.service
+Wants=obmc-host-reset-running@%i.target
+Before=obmc-host-reset-running@%i.target
+Wants=op-reset-chassis-on@%i.service
+After=op-reset-chassis-on@%i.service
+Conflicts=obmc-host-stop@%i.target
+ConditionPathExists=/run/openbmc/chassis@%i-on
+
+[Service]
+RemainAfterExit=yes
+Type=oneshot
+ExecStart=/bin/sh -c "if [ $(busctl get-property `mapper get-service /xyz/openbmc_project/Chassis/Control/Power%i` /xyz/openbmc_project/Chassis/Control/Power%i xyz.openbmc_project.Chassis.Control.Power vrd_good | sed 's/i\s*[1]/on/' | grep on | wc -l) != 0 ]; then mkdir -p /run/openbmc/ && touch /run/openbmc/host@%i-on; fi"
+SyslogIdentifier=phosphor-host-check
+
+[Install]
+WantedBy=obmc-host-reset@%i.target
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/state/phosphor-state-manager/phosphor-reset-host-reboot-attempts@.service b/meta-openbmc-mods/meta-common/recipes-phosphor/state/phosphor-state-manager/phosphor-reset-host-reboot-attempts@.service
new file mode 100644
index 000000000..87c750c57
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/state/phosphor-state-manager/phosphor-reset-host-reboot-attempts@.service
@@ -0,0 +1,14 @@
+[Unit]
+Description=Reset host reboot counter
+Wants=mapper-wait@-xyz-openbmc_project-state-host%i.service
+After=mapper-wait@-xyz-openbmc_project-state-host%i.service
+ConditionPathExists=!/run/openbmc/host@%i-on
+
+[Service]
+Restart=no
+Type=oneshot
+ExecStart=/bin/sh -c "busctl set-property `mapper get-service /xyz/openbmc_project/state/host%i` /xyz/openbmc_project/state/host%i xyz.openbmc_project.Control.Boot.RebootAttempts AttemptsLeft u 3"
+StartLimitInterval=0
+
+[Install]
+WantedBy=obmc-host-start@%i.target
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/state/phosphor-state-manager_%.bbappend b/meta-openbmc-mods/meta-common/recipes-phosphor/state/phosphor-state-manager_%.bbappend
new file mode 100644
index 000000000..92f5e530c
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/state/phosphor-state-manager_%.bbappend
@@ -0,0 +1,8 @@
+FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
+
+SRC_URI += "file://0001-Modify-dbus-interface-for-power-control.patch \
+ file://phosphor-reboot-host@.service \
+ file://phosphor-reset-host-reboot-attempts@.service \
+ file://phosphor-reset-host-check@.service \
+ file://0002-Capture-host-restart-cause.patch \
+ "
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/system/callback-manager.bb b/meta-openbmc-mods/meta-common/recipes-phosphor/system/callback-manager.bb
new file mode 100644
index 000000000..d0fdce645
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/system/callback-manager.bb
@@ -0,0 +1,19 @@
+SUMMARY = "Callback Manager"
+DESCRIPTION = "D-Bus daemon that registers matches that trigger method calls"
+
+SRC_URI = "git://git-amr-2.devtools.intel.com:29418/openbmc-provingground;protocol=ssh"
+
+inherit cmake systemd
+DEPENDS = "boost sdbusplus"
+
+PV = "0.1+git${SRCPV}"
+SRCREV = "3cc86d6c536b4c5ee7afb5447837b83ce8b3d149"
+
+S = "${WORKDIR}/git/callback-manager"
+
+SYSTEMD_SERVICE_${PN} += "callback-manager.service"
+
+LICENSE = "Apache-2.0"
+LIC_FILES_CHKSUM = "file://LICENCE;md5=7becf906c8f8d03c237bad13bc3dac53"
+
+EXTRA_OECMAKE = "-DYOCTO=1"
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/system/obmc-mgr-system%.bbappend b/meta-openbmc-mods/meta-common/recipes-phosphor/system/obmc-mgr-system%.bbappend
new file mode 100644
index 000000000..37bb8f961
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/system/obmc-mgr-system%.bbappend
@@ -0,0 +1,2 @@
+SYSTEMD_AUTO_ENABLE = "enable"
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/users/phosphor-user-manager/0005-Added-suport-for-multiple-user-manager-services.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/users/phosphor-user-manager/0005-Added-suport-for-multiple-user-manager-services.patch
new file mode 100644
index 000000000..332933a28
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/users/phosphor-user-manager/0005-Added-suport-for-multiple-user-manager-services.patch
@@ -0,0 +1,1648 @@
+From 4762913cfbd45234ddb363a5ec130eb56a8c7af0 Mon Sep 17 00:00:00 2001
+From: Radivoje Jovanovic <radivoje.jovanovic@intel.com>
+Date: Mon, 2 Jul 2018 19:23:25 -0700
+Subject: [PATCH] Added suport for multiple user manager services
+
+Support added for SSSD service implementation
+
+Signed-off-by: Alberto Salazar Perez <alberto.salazar.perez@intel.com>
+Signed-off-by: Radivoje Jovanovic <radivoje.jovanovic@intel.com>
+Signed-off-by: Richard Marian Thomaiyar <richard.marian.thomaiyar@linux.intel.com>
+---
+ Makefile.am | 5 +-
+ mainapp.cpp | 89 ++++++-
+ user_mgr.cpp | 295 +++------------------
+ user_mgr.hpp | 9 +-
+ user_service.cpp | 781 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ user_service.hpp | 233 +++++++++++++++++
+ 6 files changed, 1141 insertions(+), 271 deletions(-)
+ create mode 100644 user_service.cpp
+ create mode 100644 user_service.hpp
+
+diff --git a/Makefile.am b/Makefile.am
+index 4413b84..e4310d4 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -1,12 +1,13 @@
+ sbin_PROGRAMS = phosphor-user-manager
+
+-noinst_HEADERS = user.hpp user_mgr.hpp users.hpp
++noinst_HEADERS = user.hpp user_mgr.hpp users.hpp user_service.hpp
+
+ phosphor_user_manager_SOURCES = \
+ user.cpp \
+ mainapp.cpp \
+ user_mgr.cpp \
+- users.cpp
++ users.cpp \
++ user_service.cpp
+
+ phosphor_user_manager_LDFLAGS = $(SDBUSPLUS_LIBS) \
+ $(PHOSPHOR_DBUS_INTERFACES_LIBS) \
+diff --git a/mainapp.cpp b/mainapp.cpp
+index c9da030..03c406a 100644
+--- a/mainapp.cpp
++++ b/mainapp.cpp
+@@ -14,18 +14,105 @@
+ * limitations under the License.
+ */
+ #include <string>
++#include <iostream>
++#include <getopt.h>
+ #include "user_mgr.hpp"
++#include "user_service.hpp"
+ #include "config.h"
+
+ // D-Bus root for user manager
+ constexpr auto USER_MANAGER_ROOT = "/xyz/openbmc_project/user";
+
++void printUsage()
++{
++ std::string usage =
++ R"(Usage:
++ phosphor-user-manager [OPTIONS]
++
++Backend DBUS service for OpenBMC User Management.
++If no OPTIONS are specified, shadow file will be used.
++
++Options:
++ -s, --service={shadow|sssd}
++ Specify the authentication service to use:
++ 'shadow' will use the /etc/shadow file.
++ 'sssd' will use the sssd service domains.
++ -h, --help Displays this help message.
++)";
++ std::cerr << usage;
++}
++
++void parseArgs(int argc, char** argv,
++ phosphor::user::UserService::ServiceType& srvc)
++{
++ const std::string shortOpts{"s:h"};
++ const struct option longOpts[] = {{"service", 1, nullptr, 's'},
++ {"help", 0, nullptr, 'h'},
++ {nullptr, 0, nullptr, 0}};
++
++ while (true)
++ {
++ const auto opt =
++ getopt_long(argc, argv, shortOpts.c_str(), longOpts, nullptr);
++
++ if (opt == -1)
++ {
++ if (srvc == phosphor::user::UserService::ServiceType::none)
++ {
++ srvc = phosphor::user::UserService::ServiceType::shadow;
++ }
++ break;
++ }
++
++ switch (opt)
++ {
++ case 's':
++ {
++ std::string srvcStr{optarg};
++ if (!srvcStr.compare("shadow"))
++ {
++ srvc = phosphor::user::UserService::ServiceType::shadow;
++ }
++ else if (!srvcStr.compare("sssd"))
++ {
++ srvc = phosphor::user::UserService::ServiceType::sssd;
++ }
++ else
++ {
++ std::cerr << "Error. '" << srvcStr << "' is not a valid"
++ << " authentication service." << std::endl;
++ printUsage();
++ exit(1);
++ }
++ }
++ break;
++
++ case 'h':
++ {
++ printUsage();
++ exit(0);
++ }
++
++ default:
++ {
++ printUsage();
++ exit(1);
++ }
++ }
++ }
++}
++
+ int main(int argc, char** argv)
+ {
++ // Check command line options. Exit if error.
++ phosphor::user::UserService::ServiceType srvc =
++ phosphor::user::UserService::ServiceType::none;
++ parseArgs(argc, argv, srvc);
++
+ auto bus = sdbusplus::bus::new_default();
+ sdbusplus::server::manager::manager objManager(bus, USER_MANAGER_ROOT);
+
+- phosphor::user::UserMgr userMgr(bus, USER_MANAGER_ROOT);
++ phosphor::user::UserMgr userMgr(bus, USER_MANAGER_ROOT, srvc);
+
+ // Claim the bus now
+ bus.request_name(USER_MANAGER_BUSNAME);
+diff --git a/user_mgr.cpp b/user_mgr.cpp
+index 786a8fd..51193cc 100644
+--- a/user_mgr.cpp
++++ b/user_mgr.cpp
+@@ -14,26 +14,18 @@
+ // limitations under the License.
+ */
+
+-#include <shadow.h>
+-#include <unistd.h>
+-#include <sys/types.h>
+-#include <sys/wait.h>
++#include <cstdio>
++
+ #include <fstream>
+-#include <grp.h>
+-#include <pwd.h>
+ #include <regex>
+-#include <algorithm>
+-#include <numeric>
+-#include <boost/process/child.hpp>
+-#include <boost/process/io.hpp>
+ #include <boost/algorithm/string/split.hpp>
+ #include <xyz/openbmc_project/Common/error.hpp>
+ #include <xyz/openbmc_project/User/Common/error.hpp>
+ #include <phosphor-logging/log.hpp>
+ #include <phosphor-logging/elog.hpp>
+ #include <phosphor-logging/elog-errors.hpp>
++#include <stdexcept>
+ #include "shadowlock.hpp"
+-#include "file.hpp"
+ #include "user_mgr.hpp"
+ #include "users.hpp"
+ #include "config.h"
+@@ -43,12 +35,10 @@ namespace phosphor
+ namespace user
+ {
+
+-static constexpr const char *passwdFileName = "/etc/passwd";
+ static constexpr size_t ipmiMaxUsers = 15;
+ static constexpr size_t ipmiMaxUserNameLen = 16;
+ static constexpr size_t systemMaxUserNameLen = 30;
+ static constexpr size_t maxSystemUsers = 30;
+-static constexpr const char *grpSsh = "ssh";
+ static constexpr uint8_t minPasswdLength = 8;
+ static constexpr int success = 0;
+ static constexpr int failure = -1;
+@@ -83,79 +73,6 @@ using NoResource =
+
+ using Argument = xyz::openbmc_project::Common::InvalidArgument;
+
+-template <typename... ArgTypes>
+-static std::vector<std::string> executeCmd(const char *path,
+- ArgTypes &&... tArgs)
+-{
+- std::vector<std::string> stdOutput;
+- boost::process::ipstream stdOutStream;
+- boost::process::child execProg(path, const_cast<char *>(tArgs)...,
+- boost::process::std_out > stdOutStream);
+- std::string stdOutLine;
+-
+- while (stdOutStream && std::getline(stdOutStream, stdOutLine) &&
+- !stdOutLine.empty())
+- {
+- stdOutput.emplace_back(stdOutLine);
+- }
+-
+- execProg.wait();
+-
+- int retCode = execProg.exit_code();
+- if (retCode)
+- {
+- log<level::ERR>("Command execution failed", entry("PATH=%d", path),
+- entry("RETURN_CODE:%d", retCode));
+- elog<InternalFailure>();
+- }
+-
+- return stdOutput;
+-}
+-
+-static std::string getCSVFromVector(std::vector<std::string> vec)
+-{
+- switch (vec.size())
+- {
+- case 0:
+- {
+- return "";
+- }
+- break;
+-
+- case 1:
+- {
+- return std::string{vec[0]};
+- }
+- break;
+-
+- default:
+- {
+- return std::accumulate(
+- std::next(vec.begin()), vec.end(), vec[0],
+- [](std::string a, std::string b) { return a + ',' + b; });
+- }
+- }
+-}
+-
+-static bool removeStringFromCSV(std::string &csvStr, const std::string &delStr)
+-{
+- std::string::size_type delStrPos = csvStr.find(delStr);
+- if (delStrPos != std::string::npos)
+- {
+- // need to also delete the comma char
+- if (delStrPos == 0)
+- {
+- csvStr.erase(delStrPos, delStr.size() + 1);
+- }
+- else
+- {
+- csvStr.erase(delStrPos - 1, delStr.size() + 1);
+- }
+- return true;
+- }
+- return false;
+-}
+-
+ bool UserMgr::isUserExist(const std::string &userName)
+ {
+ if (userName.empty())
+@@ -282,39 +199,14 @@ void UserMgr::createUser(std::string userName,
+ {
+ throwForInvalidPrivilege(priv);
+ throwForInvalidGroups(groupNames);
+- // All user management lock has to be based on /etc/shadow
+- phosphor::user::shadow::Lock lock();
+ throwForUserExists(userName);
+ throwForUserNameConstraints(userName, groupNames);
+ throwForMaxGrpUserCount(groupNames);
+
+- std::string groups = getCSVFromVector(groupNames);
+- bool sshRequested = removeStringFromCSV(groups, grpSsh);
++ // Tell the User Service to create a new user with the info provided.
++ userSrvc->createUser(userName, groupNames, priv, enabled);
+
+- // treat privilege as a group - This is to avoid using different file to
+- // store the same.
+- if (!priv.empty())
+- {
+- if (groups.size() != 0)
+- {
+- groups += ",";
+- }
+- groups += priv;
+- }
+- try
+- {
+- executeCmd("/usr/sbin/useradd", userName.c_str(), "-G", groups.c_str(),
+- "-m", "-N", "-s",
+- (sshRequested ? "/bin/sh" : "/bin/nologin"), "-e",
+- (enabled ? "" : "1970-01-02"));
+- }
+- catch (const InternalFailure &e)
+- {
+- log<level::ERR>("Unable to create new user");
+- elog<InternalFailure>();
+- }
+-
+- // Add the users object before sending out the signal
++ // Add the users to the local list before sending out the signal
+ std::string userObj = std::string(usersObjPath) + "/" + userName;
+ std::sort(groupNames.begin(), groupNames.end());
+ usersList.emplace(
+@@ -328,19 +220,11 @@ void UserMgr::createUser(std::string userName,
+
+ void UserMgr::deleteUser(std::string userName)
+ {
+- // All user management lock has to be based on /etc/shadow
+- phosphor::user::shadow::Lock lock();
+ throwForUserDoesNotExist(userName);
+- try
+- {
+- executeCmd("/usr/sbin/userdel", userName.c_str(), "-r");
+- }
+- catch (const InternalFailure &e)
+- {
+- log<level::ERR>("User delete failed",
+- entry("USER_NAME=%s", userName.c_str()));
+- elog<InternalFailure>();
+- }
++
++ // Tell the User Service to delete user
++ userSrvc->deleteUser(userName);
++ // Then delete user from local list
+
+ usersList.erase(userName);
+
+@@ -351,24 +235,13 @@ void UserMgr::deleteUser(std::string userName)
+
+ void UserMgr::renameUser(std::string userName, std::string newUserName)
+ {
+- // All user management lock has to be based on /etc/shadow
+- phosphor::user::shadow::Lock lock();
+ throwForUserDoesNotExist(userName);
+ throwForUserExists(newUserName);
+ throwForUserNameConstraints(newUserName,
+ usersList[userName].get()->userGroups());
+- try
+- {
+- std::string newHomeDir = "/home/" + newUserName;
+- executeCmd("/usr/sbin/usermod", "-l", newUserName.c_str(),
+- userName.c_str(), "-d", newHomeDir.c_str(), "-m");
+- }
+- catch (const InternalFailure &e)
+- {
+- log<level::ERR>("User rename failed",
+- entry("USER_NAME=%s", userName.c_str()));
+- elog<InternalFailure>();
+- }
++ // Call The User Service to rename user on the system
++ userSrvc->renameUser(userName, newUserName);
++ // Update local list to reflect the name change
+ const auto &user = usersList[userName];
+ std::string priv = user.get()->userPrivilege();
+ std::vector<std::string> groupNames = user.get()->userGroups();
+@@ -392,8 +265,6 @@ void UserMgr::updateGroupsAndPriv(const std::string &userName,
+ {
+ throwForInvalidPrivilege(priv);
+ throwForInvalidGroups(groupNames);
+- // All user management lock has to be based on /etc/shadow
+- phosphor::user::shadow::Lock lock();
+ throwForUserDoesNotExist(userName);
+ const std::vector<std::string> &oldGroupNames =
+ usersList[userName].get()->userGroups();
+@@ -409,29 +280,8 @@ void UserMgr::updateGroupsAndPriv(const std::string &userName,
+ throwForMaxGrpUserCount(groupNames);
+ }
+
+- std::string groups = getCSVFromVector(groupNames);
+- bool sshRequested = removeStringFromCSV(groups, grpSsh);
+-
+- // treat privilege as a group - This is to avoid using different file to
+- // store the same.
+- if (!priv.empty())
+- {
+- if (groups.size() != 0)
+- {
+- groups += ",";
+- }
+- groups += priv;
+- }
+- try
+- {
+- executeCmd("/usr/sbin/usermod", userName.c_str(), "-G", groups.c_str(),
+- "-s", (sshRequested ? "/bin/sh" : "/bin/nologin"));
+- }
+- catch (const InternalFailure &e)
+- {
+- log<level::ERR>("Unable to modify user privilege / groups");
+- elog<InternalFailure>();
+- }
++ // Call The User Service to update user groups and priv on the system
++ userSrvc->updateGroupsAndPriv(userName, groupNames, priv);
+
+ log<level::INFO>("User groups / privilege updated successfully",
+ entry("USER_NAME=%s", userName.c_str()));
+@@ -627,19 +477,9 @@ int UserMgr::setPamModuleArgValue(const std::string &moduleName,
+
+ void UserMgr::userEnable(const std::string &userName, bool enabled)
+ {
+- // All user management lock has to be based on /etc/shadow
+- phosphor::user::shadow::Lock lock();
+ throwForUserDoesNotExist(userName);
+- try
+- {
+- executeCmd("/usr/sbin/usermod", userName.c_str(), "-e",
+- (enabled ? "" : "1970-01-02"));
+- }
+- catch (const InternalFailure &e)
+- {
+- log<level::ERR>("Unable to modify user enabled state");
+- elog<InternalFailure>();
+- }
++ // Call The User Service to update user groups and priv on the system
++ userSrvc->updateUserStatus(userName, enabled);
+
+ log<level::INFO>("User enabled/disabled state updated successfully",
+ entry("USER_NAME=%s", userName.c_str()),
+@@ -730,49 +570,8 @@ bool UserMgr::userLockedForFailedAttempt(const std::string &userName,
+
+ UserSSHLists UserMgr::getUserAndSshGrpList()
+ {
+- // All user management lock has to be based on /etc/shadow
+- phosphor::user::shadow::Lock lock();
+-
+- std::vector<std::string> userList;
+- std::vector<std::string> sshUsersList;
+- struct passwd pw, *pwp = nullptr;
+- std::array<char, 1024> buffer{};
+-
+- phosphor::user::File passwd(passwdFileName, "r");
+- if ((passwd)() == NULL)
+- {
+- log<level::ERR>("Error opening the passwd file");
+- elog<InternalFailure>();
+- }
+-
+- while (true)
+- {
+- auto r = fgetpwent_r((passwd)(), &pw, buffer.data(), buffer.max_size(),
+- &pwp);
+- if ((r != 0) || (pwp == NULL))
+- {
+- // Any error, break the loop.
+- break;
+- }
+- // Add all users whose UID >= 1000 and < 65534
+- // and special UID 0.
+- if ((pwp->pw_uid == 0) ||
+- ((pwp->pw_uid >= 1000) && (pwp->pw_uid < 65534)))
+- {
+- std::string userName(pwp->pw_name);
+- userList.emplace_back(userName);
+-
+- // ssh doesn't have separate group. Check login shell entry to
+- // get all users list which are member of ssh group.
+- std::string loginShell(pwp->pw_shell);
+- if (loginShell == "/bin/sh")
+- {
+- sshUsersList.emplace_back(userName);
+- }
+- }
+- }
+- endpwent();
+- return std::make_pair(std::move(userList), std::move(sshUsersList));
++ // Call The User Service to get the User and SSUsers lists
++ return std::move(userSrvc->getUserAndSshGrpList());
+ }
+
+ size_t UserMgr::getIpmiUsersCount()
+@@ -783,60 +582,23 @@ size_t UserMgr::getIpmiUsersCount()
+
+ bool UserMgr::isUserEnabled(const std::string &userName)
+ {
+- // All user management lock has to be based on /etc/shadow
+- phosphor::user::shadow::Lock lock();
+- std::array<char, 4096> buffer{};
+- struct spwd spwd;
+- struct spwd *resultPtr = nullptr;
+- int status = getspnam_r(userName.c_str(), &spwd, buffer.data(),
+- buffer.max_size(), &resultPtr);
+- if (!status && (&spwd == resultPtr))
+- {
+- if (resultPtr->sp_expire >= 0)
+- {
+- return false; // user locked out
+- }
+- return true;
+- }
+- return false; // assume user is disabled for any error.
++ // Call The User Service to verify if user is enabled
++ return userSrvc->isUserEnabled(userName);
+ }
+
+ std::vector<std::string> UserMgr::getUsersInGroup(const std::string &groupName)
+ {
+- std::vector<std::string> usersInGroup;
+- // Should be more than enough to get the pwd structure.
+- std::array<char, 4096> buffer{};
+- struct group grp;
+- struct group *resultPtr = nullptr;
+-
+- int status = getgrnam_r(groupName.c_str(), &grp, buffer.data(),
+- buffer.max_size(), &resultPtr);
+-
+- if (!status && (&grp == resultPtr))
+- {
+- for (; *(grp.gr_mem) != NULL; ++(grp.gr_mem))
+- {
+- usersInGroup.emplace_back(*(grp.gr_mem));
+- }
+- }
+- else
+- {
+- log<level::ERR>("Group not found",
+- entry("GROUP=%s", groupName.c_str()));
+- // Don't throw error, just return empty userList - fallback
+- }
+- return usersInGroup;
++ // Call The User Service to get the users that belong to a group
++ return std::move(userSrvc->getUsersInGroup(groupName));
+ }
+
+ void UserMgr::initUserObjects(void)
+ {
+ // All user management lock has to be based on /etc/shadow
+ phosphor::user::shadow::Lock lock();
+- std::vector<std::string> userNameList;
+- std::vector<std::string> sshGrpUsersList;
+ UserSSHLists userSSHLists = getUserAndSshGrpList();
+- userNameList = std::move(userSSHLists.first);
+- sshGrpUsersList = std::move(userSSHLists.second);
++ std::vector<std::string> userNameList = std::move(userSSHLists.first);
++ std::vector<std::string> sshGrpUsersList = std::move(userSSHLists.second);
+
+ if (!userNameList.empty())
+ {
+@@ -891,8 +653,10 @@ void UserMgr::initUserObjects(void)
+ }
+ }
+
+-UserMgr::UserMgr(sdbusplus::bus::bus &bus, const char *path) :
+- UserMgrIface(bus, path), AccountPolicyIface(bus, path), bus(bus), path(path)
++UserMgr::UserMgr(sdbusplus::bus::bus &bus, const char *path,
++ UserService::ServiceType srvc) :
++ UserMgrIface(bus, path),
++ AccountPolicyIface(bus, path), bus(bus), path(path)
+ {
+ UserMgrIface::allPrivileges(privMgr);
+ std::sort(groupsMgr.begin(), groupsMgr.end());
+@@ -1000,6 +764,7 @@ UserMgr::UserMgr(sdbusplus::bus::bus &bus, const char *path) :
+ }
+ AccountPolicyIface::accountUnlockTimeout(value32);
+ }
++ userSrvc = std::make_unique<UserService>(srvc, groupsMgr, privMgr);
+ initUserObjects();
+ }
+
+diff --git a/user_mgr.hpp b/user_mgr.hpp
+index c1673f1..169f121 100644
+--- a/user_mgr.hpp
++++ b/user_mgr.hpp
+@@ -20,6 +20,7 @@
+ #include <xyz/openbmc_project/User/AccountPolicy/server.hpp>
+ #include <unordered_map>
+ #include "users.hpp"
++#include "user_service.hpp"
+
+ namespace phosphor
+ {
+@@ -27,8 +28,6 @@ namespace user
+ {
+
+ using UserMgrIface = sdbusplus::xyz::openbmc_project::User::server::Manager;
+-using UserSSHLists =
+- std::pair<std::vector<std::string>, std::vector<std::string>>;
+ using AccountPolicyIface =
+ sdbusplus::xyz::openbmc_project::User::server::AccountPolicy;
+
+@@ -49,8 +48,10 @@ class UserMgr : public UserMgrIface, AccountPolicyIface
+ *
+ * @param[in] bus - sdbusplus handler
+ * @param[in] path - D-Bus path
++ * @param[in] srvc - User service to be used
+ */
+- UserMgr(sdbusplus::bus::bus &bus, const char *path);
++ UserMgr(sdbusplus::bus::bus &bus, const char *path,
++ UserService::ServiceType srvc);
+
+ /** @brief create user method.
+ * This method creates a new user as requested
+@@ -148,6 +149,8 @@ class UserMgr : public UserMgrIface, AccountPolicyIface
+ /** @brief object path */
+ const std::string path;
+
++ /** @brief user service to be used */
++ std::unique_ptr<UserService> userSrvc;
+ /** @brief privilege manager container */
+ std::vector<std::string> privMgr = {"priv-admin", "priv-operator",
+ "priv-user", "priv-callback"};
+diff --git a/user_service.cpp b/user_service.cpp
+new file mode 100644
+index 0000000..9bb602c
+--- /dev/null
++++ b/user_service.cpp
+@@ -0,0 +1,781 @@
++/*
++// Copyright (c) 2018 Intel Corporation
++//
++// Licensed under the Apache License, Version 2.0 (the "License");
++// you may not use this file except in compliance with the License.
++// You may obtain a copy of the License at
++//
++// http://www.apache.org/licenses/LICENSE-2.0
++//
++// Unless required by applicable law or agreed to in writing, software
++// distributed under the License is distributed on an "AS IS" BASIS,
++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
++// See the License for the specific language governing permissions and
++// limitations under the License.
++*/
++
++#include <grp.h>
++#include <pwd.h>
++#include <numeric>
++#include <boost/process/child.hpp>
++#include <boost/process/io.hpp>
++#include <boost/algorithm/string/split.hpp>
++#include "shadowlock.hpp"
++#include "file.hpp"
++#include "user_service.hpp"
++
++/* anonymous namespace for User Service interface implementations.
++// Each class inside this namespace implements a special service
++// to be used for the User Manager class. This can be extended to use
++// other user management services and it should be as simple as
++// adding a new class which inherits from phosphor::user::UserServiceInterface
++*/
++
++namespace
++{
++
++std::string getCSVFromVector(std::vector<std::string> vec)
++{
++ switch (vec.size())
++ {
++ case 0:
++ {
++ return "";
++ }
++ break;
++
++ case 1:
++ {
++ return std::string{vec[0]};
++ }
++ break;
++
++ default:
++ {
++ return std::accumulate(
++ std::next(vec.begin()), vec.end(), vec[0],
++ [](std::string a, std::string b) { return a + ',' + b; });
++ }
++ }
++}
++
++bool removeStringFromCSV(std::string &csvStr, const std::string &delStr)
++{
++ std::string::size_type delStrPos = csvStr.find(delStr);
++ if (delStrPos != std::string::npos)
++ {
++ // need to also delete the comma char
++ if (delStrPos == 0)
++ {
++ csvStr.erase(delStrPos, delStr.size() + 1);
++ }
++ else
++ {
++ csvStr.erase(delStrPos - 1, delStr.size() + 1);
++ }
++ return true;
++ }
++ return false;
++}
++
++class ShadowService : public phosphor::user::UserServiceInterface
++{
++ public:
++ ShadowService() = default;
++
++ ~ShadowService() = default;
++
++ phosphor::user::UserSSHLists getUserAndSshGrpList() const override
++ {
++ // All user management lock has to be based on /etc/shadow
++ phosphor::user::shadow::Lock lock();
++
++ std::vector<std::string> userList;
++ std::vector<std::string> sshUsersList;
++
++ struct passwd pw, *pwp = nullptr;
++ std::array<char, 1024> buffer{};
++
++ phosphor::user::File passwd(passwdFileName, "r");
++ if ((passwd)() == NULL)
++ {
++ phosphor::logging::log<phosphor::logging::level::ERR>(
++ "Error opening the passwd file");
++ phosphor::logging::elog<phosphor::user::InternalFailure>();
++ }
++
++ while (true)
++ {
++ auto r = fgetpwent_r((passwd)(), &pw, buffer.data(),
++ buffer.max_size(), &pwp);
++ if ((r != 0) || (pwp == NULL))
++ {
++ // Any error, break the loop.
++ break;
++ }
++ // Add all users whose UID >= 1000 and < 65534
++ // and special UID 0.
++ if ((pwp->pw_uid == 0) ||
++ ((pwp->pw_uid >= 1000) && (pwp->pw_uid < 65534)))
++ {
++ std::string userName(pwp->pw_name);
++ userList.emplace_back(userName);
++
++ // ssh doesn't have separate group. Check login shell entry to
++ // get all users list which are member of ssh group.
++ std::string loginShell(pwp->pw_shell);
++ if (loginShell == "/bin/sh")
++ {
++ sshUsersList.emplace_back(userName);
++ }
++ }
++ }
++ endpwent();
++ return std::make_pair(std::move(userList), std::move(sshUsersList));
++ }
++
++ std::vector<std::string>
++ getUsersInGroup(const std::string &groupName) const override
++ {
++ std::vector<std::string> usersInGroup;
++ // Should be more than enough to get the pwd structure.
++ std::array<char, 4096> buffer{};
++ struct group grp;
++ struct group *grpPtr = &grp;
++ struct group *resultPtr;
++
++ int status = getgrnam_r(groupName.c_str(), grpPtr, buffer.data(),
++ buffer.max_size(), &resultPtr);
++
++ if (!status && (grpPtr == resultPtr))
++ {
++ for (; *(grp.gr_mem) != NULL; ++(grp.gr_mem))
++ {
++ usersInGroup.emplace_back(*(grp.gr_mem));
++ }
++ }
++ else
++ {
++ phosphor::logging::log<phosphor::logging::level::ERR>(
++ "Group not found",
++ phosphor::logging::entry("GROUP=%s", groupName.c_str()));
++ // Don't throw error, just return empty usersInGroup - fallback
++ }
++ return usersInGroup;
++ }
++
++ void createUser(const std::string &userName,
++ const std::vector<std::string> &groupNames,
++ const std::string &priv, const bool &enabled) const override
++ {
++ // All user management lock has to be based on /etc/shadow
++ phosphor::user::shadow::Lock lock();
++
++ std::string groups = getCSVFromVector(groupNames);
++ bool sshRequested = removeStringFromCSV(groups, phosphor::user::grpSsh);
++
++ // treat privilege as a group - This is to avoid using different file to
++ // store the same
++ if (!priv.empty())
++ {
++ if (groups.size() != 0)
++ {
++ groups.append(",");
++ }
++ groups.append(priv);
++ }
++
++ try
++ {
++ phosphor::user::executeCmd(
++ "/usr/sbin/useradd", userName.c_str(), "-G", groups.c_str(),
++ "-m", "-N", "-s", (sshRequested ? "/bin/sh" : "/bin/nologin"),
++ "-e", (enabled ? "" : "1970-01-02"));
++ }
++ catch (const phosphor::user::InternalFailure &e)
++ {
++ phosphor::logging::log<phosphor::logging::level::ERR>(
++ "Unable to create new user");
++ phosphor::logging::elog<phosphor::user::InternalFailure>();
++ }
++ }
++
++ void renameUser(const std::string &userName,
++ const std::string &newUserName) const override
++ {
++ // All user management lock has to be based on /etc/shadow
++ phosphor::user::shadow::Lock lock();
++ try
++ {
++ std::string newHomeDir = "/home/" + newUserName;
++ phosphor::user::executeCmd("/usr/sbin/usermod", "-l",
++ newUserName.c_str(), userName.c_str(),
++ "-d", newHomeDir.c_str(), "-m");
++ }
++ catch (const phosphor::user::InternalFailure &e)
++ {
++ phosphor::logging::log<phosphor::logging::level::INFO>(
++ "User rename failed",
++ phosphor::logging::entry("USER_NAME=%s", userName.c_str()));
++ phosphor::logging::elog<phosphor::user::InternalFailure>();
++ }
++ }
++
++ void deleteUser(const std::string &userName) const override
++ {
++ // All user management lock has to be based on /etc/shadow
++ phosphor::user::shadow::Lock lock();
++
++ try
++ {
++ phosphor::user::executeCmd("/usr/sbin/userdel", userName.c_str(),
++ "-r");
++ }
++ catch (const phosphor::user::InternalFailure &e)
++ {
++ phosphor::logging::log<phosphor::logging::level::INFO>(
++ "User delete failed",
++ phosphor::logging::entry("USER_NAME=%s", userName.c_str()));
++ phosphor::logging::elog<phosphor::user::InternalFailure>();
++ }
++ }
++
++ void updateGroupsAndPriv(const std::string &userName,
++ const std::vector<std::string> &groupNames,
++ const std::string &priv) const override
++ {
++ // All user management lock has to be based on /etc/shadow
++ phosphor::user::shadow::Lock lock();
++
++ std::string groups = getCSVFromVector(groupNames);
++ bool sshRequested = removeStringFromCSV(groups, phosphor::user::grpSsh);
++
++ // treat privilege as a group - This is to avoid using different file to
++ // store the same.
++ if (!priv.empty())
++ {
++ if (groups.size() != 0)
++ {
++ groups += ",";
++ }
++ groups += priv;
++ }
++
++ try
++ {
++ phosphor::user::executeCmd(
++ "/usr/sbin/usermod", userName.c_str(), "-G", groups.c_str(),
++ "-s", (sshRequested ? "/bin/sh" : "/bin/nologin"));
++ }
++ catch (const phosphor::user::InternalFailure &e)
++ {
++ phosphor::logging::log<phosphor::logging::level::ERR>(
++ "Unable to modify user privilege / groups");
++ phosphor::logging::elog<phosphor::user::InternalFailure>();
++ }
++ }
++
++ void updateUserStatus(const std::string &userName,
++ const bool &enabled) const override
++ {
++ // All user management lock has to be based on /etc/shadow
++ phosphor::user::shadow::Lock lock();
++ try
++ {
++ phosphor::user::executeCmd("/usr/sbin/usermod", userName.c_str(),
++ "-e", (enabled ? "" : "1970-01-02"));
++ }
++ catch (const phosphor::user::InternalFailure &e)
++ {
++ phosphor::logging::log<phosphor::logging::level::ERR>(
++ "Unable to modify user enabled state");
++ phosphor::logging::elog<phosphor::user::InternalFailure>();
++ }
++ }
++
++ bool isUserEnabled(const std::string &userName) const override
++ {
++ // All user management lock has to be based on /etc/shadow
++ phosphor::user::shadow::Lock lock();
++ std::array<char, 4096> buffer{};
++ struct spwd spwd;
++ struct spwd *resultPtr = nullptr;
++ int status = getspnam_r(userName.c_str(), &spwd, buffer.data(),
++ buffer.max_size(), &resultPtr);
++ if (!status && (&spwd == resultPtr))
++ {
++ if (resultPtr->sp_expire >= 0)
++ {
++ return false; // user locked out
++ }
++ return true;
++ }
++ return false; // assume user is disabled for any error.
++ }
++
++ std::vector<std::string>
++ getUserGroups(const std::string &userName) const override
++ {
++ phosphor::logging::log<phosphor::logging::level::ERR>(
++ "ShadowService::getUserGroups not implemented!");
++ phosphor::logging::elog<phosphor::user::InternalFailure>();
++ return std::vector<std::string>();
++ }
++
++ void createGroup(const std::string &groupName) const override
++ {
++ phosphor::logging::log<phosphor::logging::level::ERR>(
++ "ShadowService::createGroup not implemented!");
++ phosphor::logging::elog<phosphor::user::InternalFailure>();
++ }
++
++ private:
++ static constexpr const char *passwdFileName = "/etc/passwd";
++};
++
++class SSSDService : public phosphor::user::UserServiceInterface
++{
++ public:
++ SSSDService(const std::vector<std::string> &groups,
++ const std::vector<std::string> &privs)
++ {
++
++ createGroup(lockedGrp);
++ for (const auto &g : groups)
++ {
++ createGroup(g);
++ }
++ for (const auto &p : privs)
++ {
++ createGroup(p);
++ }
++ }
++
++ ~SSSDService() = default;
++
++ phosphor::user::UserSSHLists getUserAndSshGrpList() const override
++ {
++ std::vector<std::string> users;
++ std::vector<std::string> sshGroup;
++ std::vector<std::string> exeOutput;
++
++ try
++ {
++ exeOutput = phosphor::user::executeCmd("/usr/bin/getent", "-s",
++ "sss", "passwd");
++ }
++ catch (const phosphor::user::InternalFailure &e)
++ {
++ phosphor::logging::log<phosphor::logging::level::ERR>(
++ "Unable to get users information "
++ "from sssd service");
++ phosphor::logging::elog<phosphor::user::InternalFailure>();
++ }
++
++ for (const auto &userLine : exeOutput)
++ {
++ std::vector<std::string> userInfo;
++ boost::algorithm::split(userInfo, userLine,
++ boost::algorithm::is_any_of(":"));
++ // At this point userInfo is a vector containing the passwd
++ // info for the user, so we know the correct positions:
++ // 0: User name.
++ // 1: Encrypted password.
++ // 2: User ID number (UID)
++ // 3: User's group ID number (GID)
++ // 4: Full name of the user (GECOS)
++ // 5: User home directory.
++ // 6: Login shell.
++ users.emplace_back(userInfo[0]);
++
++ // ssh doesn't have separate group. Check login shell entry to
++ // get all users list which are member of ssh group.
++ if (userInfo[6] == "/bin/sh")
++ {
++ sshGroup.emplace_back(userInfo[0]);
++ }
++ }
++
++ return std::make_pair(std::move(users), std::move(sshGroup));
++ }
++
++ std::vector<std::string>
++ getUsersInGroup(const std::string &groupName) const override
++ {
++ std::vector<std::string> userList;
++ std::vector<std::string> exeOutput;
++
++ try
++ {
++ exeOutput = phosphor::user::executeCmd("/usr/sbin/sss_groupshow",
++ groupName.c_str());
++ }
++ catch (const phosphor::user::InternalFailure &e)
++ {
++ phosphor::logging::log<phosphor::logging::level::ERR>(
++ "Unable to get group users from sssd service");
++ // Don't throw error, just return empty usersInGroup - return
++ return userList;
++ }
++ // exeOutput should have 5 entries
++ // 0: Group
++ // 1: GID number
++ // 2: Member users
++ // 3: Is a member of
++ // 4: Member groups
++ exeOutput[2].erase(
++ exeOutput[2].begin(),
++ std::find(exeOutput[2].begin(), exeOutput[2].end(), ':'));
++ boost::algorithm::trim_left(exeOutput[2]);
++ boost::algorithm::split(userList, exeOutput[2],
++ boost::algorithm::is_any_of(","));
++ return userList;
++ }
++
++ void createUser(const std::string &userName,
++ const std::vector<std::string> &groupNames,
++ const std::string &priv, const bool &enabled) const override
++ {
++ std::string groups = getCSVFromVector(groupNames);
++ bool sshRequested = removeStringFromCSV(groups, phosphor::user::grpSsh);
++ // treat privilege as a group - This is to avoid using different file to
++ // store the same
++ if (!priv.empty())
++ {
++ if (groups.size() != 0)
++ {
++ groups += ",";
++ }
++ groups += priv;
++ }
++
++ try
++ {
++ phosphor::user::executeCmd(
++ "/usr/sbin/sss_useradd", "-m", "-G", groups.c_str(), "-s",
++ (sshRequested ? "/bin/sh" : "/bin/nologin"), userName.c_str());
++ }
++ catch (const phosphor::user::InternalFailure &e)
++ {
++ phosphor::logging::log<phosphor::logging::level::ERR>(
++ "Unable to create new user in sssd service");
++ phosphor::logging::elog<phosphor::user::InternalFailure>();
++ }
++
++ // Sometimes the SSSD service needs some time to actually
++ // reflect the changes to the local DB to the NSS service,
++ // that is why we have this sleep here ...
++ std::this_thread::sleep_for(std::chrono::seconds(1));
++ // update user status (locked/unlocked)
++ updateUserStatus(userName, enabled);
++ }
++
++ void renameUser(const std::string &userName,
++ const std::string &newUserName) const override
++ {
++ std::vector<std::string> exeOutput;
++ // Local Domain for sssd doesn't have a rename feature
++ // so we need to first create a new user and then delete
++ // the old one.
++ // The only issue with this is that the password for the
++ // user will have to be reseted since it is a new user being created.
++
++ // Get original user groups
++ std::vector<std::string> groups = getUserGroups(userName);
++ // Check if it has a "ssh" group by looking for the shell login
++ try
++ {
++ exeOutput = phosphor::user::executeCmd(
++ "/usr/bin/getent", "-s", "sss", "passwd", userName.c_str());
++ }
++ catch (const phosphor::user::InternalFailure &e)
++ {
++ phosphor::logging::log<phosphor::logging::level::ERR>(
++ "Unable to get information for user");
++ phosphor::logging::elog<phosphor::user::InternalFailure>();
++ }
++ if (exeOutput[0].find("/bin/sh"))
++ {
++ groups.emplace_back(phosphor::user::grpSsh);
++ }
++ // Call create user with the new user names and previous groups
++ // Priv is already part of the groups so that can be empty.
++ createUser(newUserName, groups, "", isUserEnabled(userName));
++
++ // Now delete original user
++ deleteUser(userName);
++ }
++
++ void deleteUser(const std::string &userName) const override
++ {
++ try
++ {
++ phosphor::user::executeCmd("/usr/sbin/sss_userdel", "-r",
++ userName.c_str());
++ }
++ catch (const phosphor::user::InternalFailure &e)
++ {
++ phosphor::logging::log<phosphor::logging::level::ERR>(
++ "Unable to delete user from sssd service");
++ phosphor::logging::elog<phosphor::user::InternalFailure>();
++ }
++ }
++
++ void updateGroupsAndPriv(const std::string &userName,
++ const std::vector<std::string> &groupNames,
++ const std::string &priv) const override
++ {
++ // local domain sssd do not allow to update all list of groups,
++ // so we will remove all groups first (except for the user one)
++ // and then all all the ones that were passed
++ std::string oldGroups = getCSVFromVector(getUserGroups(userName));
++ std::string groups = getCSVFromVector(groupNames);
++ bool sshRequested = removeStringFromCSV(groups, phosphor::user::grpSsh);
++ // treat privilege as a group - This is to avoid using different file to
++ // store the same
++ if (!priv.empty())
++ {
++ if (groups.size() != 0)
++ {
++ groups += ",";
++ }
++ groups += priv;
++ }
++ try
++ {
++ phosphor::user::executeCmd(
++ "/usr/sbin/sss_usermod", "-r", oldGroups.c_str(), "-a",
++ groups.c_str(), "-s",
++ (sshRequested ? "/bin/sh" : "/bin/nologin"), userName.c_str());
++ }
++ catch (const phosphor::user::InternalFailure &e)
++ {
++ phosphor::logging::log<phosphor::logging::level::ERR>(
++ "Unable to update user groups and "
++ "priv from sssd service");
++ phosphor::logging::elog<phosphor::user::InternalFailure>();
++ }
++ }
++
++ void updateUserStatus(const std::string &userName,
++ const bool &enabled) const override
++ {
++ std::string enabledStr;
++ std::string lockedStr;
++ if (isUserEnabled(userName) == enabled)
++ {
++ return;
++ }
++ if (enabled)
++ {
++ enabledStr = "-r";
++ lockedStr = "-U";
++ }
++ else
++ {
++ enabledStr = "-a";
++ lockedStr = "-L";
++ }
++ try
++ {
++ // We will add a special locked group to identify the users
++ // that have been locked out of the system.
++ // TODO: sss_usermod is not locking user accounts for the
++ // LOCAL domain, need to find the correct PAM configuration
++ // to actually lockout users for SSSD.
++ // As a workaround we are using the pam module pam_listfile.so
++ // to lockout all users that belong to the locked group.
++ phosphor::user::executeCmd("/usr/sbin/sss_usermod",
++ enabledStr.c_str(), lockedGrp.c_str(),
++ lockedStr.c_str(), userName.c_str());
++ }
++ catch (const phosphor::user::InternalFailure &e)
++ {
++ phosphor::logging::log<phosphor::logging::level::ERR>(
++ "Unable to update user status from sssd service");
++ phosphor::logging::elog<phosphor::user::InternalFailure>();
++ }
++ }
++
++ bool isUserEnabled(const std::string &userName) const override
++ {
++ std::vector<std::string> userGrps = getUserGroups(userName);
++ return std::find(userGrps.begin(), userGrps.end(), lockedGrp) ==
++ userGrps.end();
++ }
++
++ std::vector<std::string>
++ getUserGroups(const std::string &userName) const override
++ {
++ std::vector<std::string> exeOutput;
++ try
++ {
++ exeOutput =
++ phosphor::user::executeCmd("/usr/bin/groups", userName.c_str());
++ }
++ catch (const phosphor::user::InternalFailure &e)
++ {
++ phosphor::logging::log<phosphor::logging::level::ERR>(
++ "Unable to get groups for user");
++ phosphor::logging::elog<phosphor::user::InternalFailure>();
++ }
++
++ std::vector<std::string> groups;
++ boost::algorithm::split(groups, exeOutput[0],
++ boost::algorithm::is_any_of(" "));
++ // Delete group that equals user name if it exists
++ auto userNameGroup = std::find(groups.begin(), groups.end(), userName);
++ if (userNameGroup != groups.end())
++ {
++ groups.erase(userNameGroup);
++ }
++ return groups;
++ }
++
++ void createGroup(const std::string &groupName) const override
++ {
++ try
++ {
++ if (!groupExists(groupName))
++ {
++ phosphor::user::executeCmd("/usr/sbin/sss_groupadd",
++ groupName.c_str());
++ }
++ }
++ catch (const phosphor::user::InternalFailure &e)
++ {
++ phosphor::logging::log<phosphor::logging::level::ERR>(
++ "Unable to create group");
++ phosphor::logging::elog<phosphor::user::InternalFailure>();
++ }
++ }
++
++ private:
++ static const std::string lockedGrp;
++
++ bool groupExists(const std::string &groupName) const
++ {
++ try
++ {
++ phosphor::user::executeCmd("/usr/sbin/sss_groupshow",
++ groupName.c_str());
++ }
++ catch (const phosphor::user::InternalFailure &e)
++ {
++ return false;
++ }
++ return true;
++ }
++};
++
++const std::string SSSDService::lockedGrp = "sssd_locked";
++} // anonymous namespace
++
++namespace phosphor
++{
++namespace user
++{
++
++UserService::UserService(const ServiceType &srvcType,
++ const std::vector<std::string> &groups,
++ const std::vector<std::string> &privs)
++{
++ setServiceImpl(srvcType, groups, privs);
++}
++
++void UserService::updateServiceType(const ServiceType &srvcType,
++ const std::vector<std::string> &groups,
++ const std::vector<std::string> &privs)
++{
++ usrSrvcImpl.reset();
++ setServiceImpl(srvcType, groups, privs);
++}
++
++void UserService::setServiceImpl(const ServiceType &srvcType,
++ const std::vector<std::string> &groups,
++ const std::vector<std::string> &privs)
++{
++ switch (srvcType)
++ {
++ case ServiceType::shadow:
++ {
++ usrSrvcImpl = std::make_unique<ShadowService>();
++ }
++ break;
++
++ case ServiceType::sssd:
++ {
++ usrSrvcImpl = std::make_unique<SSSDService>(groups, privs);
++ }
++ break;
++
++ case ServiceType::none:
++ default:
++ {
++ phosphor::logging::log<phosphor::logging::level::ERR>(
++ "Invalid service type initialization!");
++ phosphor::logging::elog<phosphor::user::InternalFailure>();
++ }
++ break;
++ }
++}
++
++UserService::~UserService()
++{
++}
++
++phosphor::user::UserSSHLists UserService::getUserAndSshGrpList() const
++{
++ return usrSrvcImpl->getUserAndSshGrpList();
++}
++
++std::vector<std::string>
++ UserService::getUsersInGroup(const std::string &groupName) const
++{
++ return usrSrvcImpl->getUsersInGroup(groupName);
++}
++
++void UserService::createUser(const std::string &userName,
++ const std::vector<std::string> &groupNames,
++ const std::string &priv, const bool &enabled) const
++{
++ usrSrvcImpl->createUser(userName, groupNames, priv, enabled);
++}
++
++void UserService::renameUser(const std::string &userName,
++ const std::string &newUserName) const
++{
++ usrSrvcImpl->renameUser(userName, newUserName);
++}
++
++void UserService::deleteUser(const std::string &userName) const
++{
++ usrSrvcImpl->deleteUser(userName);
++}
++
++void UserService::updateGroupsAndPriv(
++ const std::string &userName, const std::vector<std::string> &groupNames,
++ const std::string &priv) const
++{
++ usrSrvcImpl->updateGroupsAndPriv(userName, groupNames, priv);
++}
++
++void UserService::updateUserStatus(const std::string &userName,
++ const bool &enabled) const
++{
++ usrSrvcImpl->updateUserStatus(userName, enabled);
++}
++
++bool UserService::isUserEnabled(const std::string &userName) const
++{
++ return usrSrvcImpl->isUserEnabled(userName);
++}
++
++std::vector<std::string>
++ UserService::getUserGroups(const std::string &userName) const
++{
++ return usrSrvcImpl->getUserGroups(userName);
++}
++
++} // namespace user
++} // namespace phosphor
+diff --git a/user_service.hpp b/user_service.hpp
+new file mode 100644
+index 0000000..97a049b
+--- /dev/null
++++ b/user_service.hpp
+@@ -0,0 +1,233 @@
++/*
++// Copyright (c) 2018 Intel Corporation
++//
++// Licensed under the Apache License, Version 2.0 (the "License");
++// you may not use this file except in compliance with the License.
++// You may obtain a copy of the License at
++//
++// http://www.apache.org/licenses/LICENSE-2.0
++//
++// Unless required by applicable law or agreed to in writing, software
++// distributed under the License is distributed on an "AS IS" BASIS,
++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
++// See the License for the specific language governing permissions and
++// limitations under the License.
++*/
++
++#pragma once
++#include <xyz/openbmc_project/Common/error.hpp>
++#include <xyz/openbmc_project/User/Common/error.hpp>
++#include <phosphor-logging/log.hpp>
++#include <phosphor-logging/elog.hpp>
++#include <boost/process/child.hpp>
++#include <boost/process/io.hpp>
++
++namespace phosphor
++{
++namespace user
++{
++
++using UserSSHLists =
++ std::pair<std::vector<std::string>, std::vector<std::string>>;
++using InternalFailure =
++ sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
++using InsufficientPermission =
++ sdbusplus::xyz::openbmc_project::Common::Error::InsufficientPermission;
++
++const std::string grpSsh = "ssh";
++
++template <typename... ArgTypes>
++std::vector<std::string> executeCmd(const char *path, ArgTypes &&... tArgs)
++{
++ std::vector<std::string> stdOutput;
++ boost::process::ipstream stdOutStream;
++ boost::process::child execProg(path, const_cast<char *>(tArgs)...,
++ boost::process::std_out > stdOutStream);
++ std::string stdOutLine;
++
++ while (stdOutStream && std::getline(stdOutStream, stdOutLine) &&
++ !stdOutLine.empty())
++ {
++ stdOutput.emplace_back(stdOutLine);
++ }
++
++ execProg.wait();
++
++ int retCode = execProg.exit_code();
++ if (retCode)
++ {
++ phosphor::logging::log<phosphor::logging::level::ERR>(
++ "Command execution failed",
++ phosphor::logging::entry("PATH=%d", path),
++ phosphor::logging::entry("RETURN_CODE:%d", retCode));
++ phosphor::logging::elog<phosphor::user::InternalFailure>();
++ }
++
++ return stdOutput;
++}
++
++/** @class UserServiceInterface
++ * @brief Interface class for methods provided by the implemmentations
++ * of the user service. Provides the same methods as the UserService
++ * class.
++ */
++class UserServiceInterface
++{
++ public:
++ UserServiceInterface() = default;
++ virtual ~UserServiceInterface() = default;
++ virtual UserSSHLists getUserAndSshGrpList() const = 0;
++ virtual std::vector<std::string>
++ getUsersInGroup(const std::string &groupName) const = 0;
++ virtual void createUser(const std::string &userName,
++ const std::vector<std::string> &groupNames,
++ const std::string &priv,
++ const bool &enabled) const = 0;
++ virtual void renameUser(const std::string &userName,
++ const std::string &newUserName) const = 0;
++ virtual void deleteUser(const std::string &userName) const = 0;
++ virtual void updateGroupsAndPriv(const std::string &userName,
++ const std::vector<std::string> &groupNames,
++ const std::string &priv) const = 0;
++ virtual void updateUserStatus(const std::string &userName,
++ const bool &enabled) const = 0;
++ virtual bool isUserEnabled(const std::string &userName) const = 0;
++ virtual std::vector<std::string>
++ getUserGroups(const std::string &userName) const = 0;
++ virtual void createGroup(const std::string &groupName) const = 0;
++};
++
++/** @class UserService
++ * @brief Responsible for managing the user service for the user manager.
++ * This service is the one responsible to actually change the user information
++ * of the application. It can support sevaral services, currently the ones
++ * supported are:
++ *
++ * 1) Shadow: Which uses the /etc/shadow file for updating the users
++ * 2) SSSD: Which uses the sssd service for a LOCAL domain only right now.
++ */
++class UserService
++{
++ public:
++ UserService() = delete;
++ UserService(const UserService &) = delete;
++ UserService &operator=(const UserService &) = delete;
++ UserService(UserService &&) = delete;
++ UserService &operator=(UserService &&) = delete;
++
++ // Service Types implemented. None is used to validate.
++ enum class ServiceType
++ {
++ none,
++ shadow,
++ sssd
++ };
++
++ UserService(const ServiceType &srvcType,
++ const std::vector<std::string> &groups,
++ const std::vector<std::string> &privs);
++ ~UserService();
++
++ /** @brief update the current Service type of the instance.
++ * This function is used to update in real time the service
++ * being used for the user management without restarting the
++ * whole service.
++ *
++ * @param[in] srvcType
++ * @param[in] groups
++ * @param[in] privs
++ */
++ void updateServiceType(const ServiceType &srvcType,
++ const std::vector<std::string> &groups,
++ const std::vector<std::string> &privs);
++
++ /** @brief get user list and SSH group members list
++ * This method gets the list of users from the service.
++ * If the userlist reference is empty, all the users will be added
++ * and DBus notified about them. If the list is not empty, the function
++ * will only update list adding the missing ones to it. It will not remove
++ * any extra users on the list that are not part of the service!
++ *
++ */
++ UserSSHLists getUserAndSshGrpList() const;
++
++ /** @brief Get users in group.
++ * This method creates a new user as requested
++ *
++ * @param[in] groupName - Name of the group which has to be queried
++ */
++ std::vector<std::string>
++ getUsersInGroup(const std::string &groupName) const;
++
++ /** @brief create user method.
++ * This method creates a new user as requested
++ *
++ * @param[in] userName - Name of the user which has to be created
++ * @param[in] groupNames - Group names list, to which user has to be added.
++ * @param[in] priv - Privilege of the user.
++ * @param[in] enabled - State of the user enabled / disabled.
++ */
++ void createUser(const std::string &userName,
++ const std::vector<std::string> &groupNames,
++ const std::string &priv, const bool &enabled) const;
++
++ /** @brief rename user method.
++ * This method renames the user as requested
++ *
++ * @param[in] userName - current name of the user
++ * @param[in] userName - user name to which it has to be renamed.
++ */
++ void renameUser(const std::string &userName,
++ const std::string &newUserName) const;
++
++ /** @brief delete user method.
++ * This method deletes the user as requested
++ *
++ * @param[in] userName - Name of the user which has to be deleted
++ */
++ void deleteUser(const std::string &userName) const;
++
++ /** @brief Updates user Groups and Privilege.
++ *
++ * @param[in] userName - Name of the user which has to be modified
++ * @param[in] groupNames - Group names list for user.
++ * @param[in] priv - Privilege of the user.
++ */
++ void updateGroupsAndPriv(const std::string &userName,
++ const std::vector<std::string> &groupNames,
++ const std::string &priv) const;
++
++ /** @brief Updates user status
++ * If enabled = false: User will be disabled
++ * If enabled = true : User will be enabled
++ *
++ * @param[in] userName - Name of the user
++ * @param[in] enabled - Status of the user: enabled / disabled?
++ */
++ void updateUserStatus(const std::string &userName,
++ const bool &enabled) const;
++
++ /** @brief Verify if user is enabled or not
++ * If enabled returns true
++ * If not enabled returns false
++ *
++ * @param[in] userName - Name of the user
++ */
++ bool isUserEnabled(const std::string &userName) const;
++
++ /** @brief Get the list of groups a user belongs to
++ *
++ * @param[in] userName - Name of the user
++ */
++ std::vector<std::string> getUserGroups(const std::string &userName) const;
++
++ private:
++ // User service implementation.
++ void setServiceImpl(const ServiceType &srvcType,
++ const std::vector<std::string> &groups,
++ const std::vector<std::string> &privs);
++ std::unique_ptr<UserServiceInterface> usrSrvcImpl;
++};
++
++} // namespace user
++} // namespace phosphor
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/users/phosphor-user-manager_%.bbappend b/meta-openbmc-mods/meta-common/recipes-phosphor/users/phosphor-user-manager_%.bbappend
new file mode 100644
index 000000000..4a8952235
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/users/phosphor-user-manager_%.bbappend
@@ -0,0 +1,5 @@
+FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
+
+SRC_URI += " \
+ file://0005-Added-suport-for-multiple-user-manager-services.patch \
+ "
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/frb2-watchdog.bb b/meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/frb2-watchdog.bb
new file mode 100644
index 000000000..950f4932d
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/frb2-watchdog.bb
@@ -0,0 +1,35 @@
+
+SUMMARY = "FRB2 timer service"
+DESCRIPTION = "The FRB2 timer service will monitor the mailbox register 0\
+and start a watchdog for FRB2 if the data is 1(BIOS will write this value)"
+
+SRC_URI = "\
+ file://CMakeLists.txt \
+ file://frb2-watchdog.cpp \
+ "
+PV = "0.1"
+
+LICENSE = "Apache-2.0"
+LIC_FILES_CHKSUM = "file://${PHOSPHORBASE}/LICENSE;md5=19407077e42b1ba3d653da313f1f5b4e"
+
+S = "${WORKDIR}"
+
+inherit cmake
+inherit pkgconfig pythonnative
+
+DEPENDS += " \
+ systemd \
+ sdbusplus \
+ sdbusplus-native \
+ phosphor-logging \
+ phosphor-dbus-interfaces \
+ phosphor-dbus-interfaces-native \
+ boost \
+ "
+
+RDEPENDS_${PN} += " \
+ libsystemd \
+ sdbusplus \
+ phosphor-logging \
+ phosphor-dbus-interfaces \
+ "
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/frb2-watchdog/.clang-format b/meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/frb2-watchdog/.clang-format
new file mode 100644
index 000000000..dd2770837
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/frb2-watchdog/.clang-format
@@ -0,0 +1,98 @@
+---
+Language: Cpp
+# BasedOnStyle: LLVM
+AccessModifierOffset: -2
+AlignAfterOpenBracket: Align
+AlignConsecutiveAssignments: false
+AlignConsecutiveDeclarations: false
+AlignEscapedNewlinesLeft: false
+AlignOperands: true
+AlignTrailingComments: true
+AllowAllParametersOfDeclarationOnNextLine: true
+AllowShortBlocksOnASingleLine: false
+AllowShortCaseLabelsOnASingleLine: false
+AllowShortFunctionsOnASingleLine: None
+AllowShortIfStatementsOnASingleLine: false
+AllowShortLoopsOnASingleLine: false
+AlwaysBreakAfterDefinitionReturnType: None
+AlwaysBreakAfterReturnType: None
+AlwaysBreakBeforeMultilineStrings: false
+AlwaysBreakTemplateDeclarations: false
+BinPackArguments: true
+BinPackParameters: true
+BraceWrapping:
+ AfterClass: true
+ AfterControlStatement: true
+ AfterEnum: true
+ AfterFunction: true
+ AfterNamespace: true
+ AfterObjCDeclaration: true
+ AfterStruct: true
+ AfterUnion: true
+ BeforeCatch: true
+ BeforeElse: true
+ IndentBraces: false
+BreakBeforeBinaryOperators: None
+BreakBeforeBraces: Custom
+BreakBeforeTernaryOperators: true
+BreakConstructorInitializers: AfterColon
+ColumnLimit: 80
+CommentPragmas: '^ IWYU pragma:'
+ConstructorInitializerAllOnOneLineOrOnePerLine: false
+ConstructorInitializerIndentWidth: 4
+ContinuationIndentWidth: 4
+Cpp11BracedListStyle: true
+DerivePointerAlignment: true
+PointerAlignment: Left
+DisableFormat: false
+ExperimentalAutoDetectBinPacking: false
+FixNamespaceComments: true
+ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ]
+IncludeBlocks: Regroup
+IncludeCategories:
+ - Regex: '^[<"](gtest|gmock)'
+ Priority: 5
+ - Regex: '^"config.h"'
+ Priority: -1
+ - Regex: '^".*\.hpp"'
+ Priority: 1
+ - Regex: '^<.*\.h>'
+ Priority: 2
+ - Regex: '^<.*'
+ Priority: 3
+ - Regex: '.*'
+ Priority: 4
+IndentCaseLabels: true
+IndentWidth: 4
+IndentWrappedFunctionNames: true
+KeepEmptyLinesAtTheStartOfBlocks: true
+MacroBlockBegin: ''
+MacroBlockEnd: ''
+MaxEmptyLinesToKeep: 1
+NamespaceIndentation: None
+ObjCBlockIndentWidth: 2
+ObjCSpaceAfterProperty: false
+ObjCSpaceBeforeProtocolList: true
+PenaltyBreakBeforeFirstCallParameter: 19
+PenaltyBreakComment: 300
+PenaltyBreakFirstLessLess: 120
+PenaltyBreakString: 1000
+PenaltyExcessCharacter: 1000000
+PenaltyReturnTypeOnItsOwnLine: 60
+PointerAlignment: Right
+ReflowComments: true
+SortIncludes: true
+SpaceAfterCStyleCast: false
+SpaceBeforeAssignmentOperators: true
+SpaceBeforeParens: ControlStatements
+SpaceInEmptyParentheses: false
+SpacesBeforeTrailingComments: 1
+SpacesInAngles: false
+SpacesInContainerLiterals: true
+SpacesInCStyleCastParentheses: false
+SpacesInParentheses: false
+SpacesInSquareBrackets: false
+Standard: Cpp11
+TabWidth: 4
+UseTab: Never
+...
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/frb2-watchdog/CMakeLists.txt b/meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/frb2-watchdog/CMakeLists.txt
new file mode 100644
index 000000000..bd5567d31
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/frb2-watchdog/CMakeLists.txt
@@ -0,0 +1,52 @@
+cmake_minimum_required (VERSION 3.5 FATAL_ERROR)
+project (frb2-watchdog CXX)
+set (CMAKE_CXX_STANDARD 17)
+set (CMAKE_CXX_STANDARD_REQUIRED ON)
+set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti")
+set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-rtti")
+
+include_directories (${CMAKE_CURRENT_SOURCE_DIR})
+
+# boost support
+find_package (Boost REQUIRED)
+# pkg_check_modules(Boost boost REQUIRED)
+include_directories (${Boost_INCLUDE_DIRS})
+add_definitions (-DBOOST_ERROR_CODE_HEADER_ONLY)
+add_definitions (-DBOOST_SYSTEM_NO_DEPRECATED)
+add_definitions (-DBOOST_ALL_NO_LIB)
+add_definitions (-DBOOST_NO_RTTI)
+add_definitions (-DBOOST_NO_TYPEID)
+add_definitions (-DBOOST_ASIO_DISABLE_THREADS)
+
+# import libsystemd
+find_package (PkgConfig REQUIRED)
+pkg_check_modules (SYSTEMD libsystemd REQUIRED)
+include_directories (${SYSTEMD_INCLUDE_DIRS})
+link_directories (${SYSTEMD_LIBRARY_DIRS})
+
+# import sdbusplus
+find_package (PkgConfig REQUIRED)
+pkg_check_modules (SDBUSPLUSPLUS sdbusplus REQUIRED)
+include_directories (${SDBUSPLUSPLUS_INCLUDE_DIRS})
+link_directories (${SDBUSPLUSPLUS_LIBRARY_DIRS})
+
+# import phosphor-logging
+find_package (PkgConfig REQUIRED)
+pkg_check_modules (LOGGING phosphor-logging REQUIRED)
+include_directories (${LOGGING_INCLUDE_DIRS})
+link_directories (${LOGGING_LIBRARY_DIRS})
+
+# import phosphor-dbus-interfaces
+find_package (PkgConfig REQUIRED)
+pkg_check_modules (DBUSINTERFACE phosphor-dbus-interfaces REQUIRED)
+include_directories (${DBUSINTERFACE_INCLUDE_DIRS})
+link_directories (${DBUSINTERFACE_LIBRARY_DIRS})
+
+add_executable (frb2-watchdog frb2-watchdog.cpp)
+
+target_link_libraries (${PROJECT_NAME} systemd)
+target_link_libraries (${PROJECT_NAME} ${Boost_LIBRARIES})
+target_link_libraries (${PROJECT_NAME} ${SDBUSPLUSPLUS_LIBRARIES})
+target_link_libraries (${PROJECT_NAME} ${DBUSINTERFACE_LIBRARIES}
+ phosphor_logging)
+install (TARGETS frb2-watchdog DESTINATION bin)
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/frb2-watchdog/cmake-format.json b/meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/frb2-watchdog/cmake-format.json
new file mode 100644
index 000000000..583c255a3
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/frb2-watchdog/cmake-format.json
@@ -0,0 +1,12 @@
+{
+ "enum_char": ".",
+ "line_ending": "unix",
+ "bullet_char": "*",
+ "max_subargs_per_line": 99,
+ "command_case": "lower",
+ "tab_size": 4,
+ "line_width": 80,
+ "separate_fn_name_with_space": true,
+ "dangle_parens": true,
+ "separate_ctrl_name_with_space": true
+} \ No newline at end of file
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/frb2-watchdog/frb2-watchdog.cpp b/meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/frb2-watchdog/frb2-watchdog.cpp
new file mode 100644
index 000000000..5356e95db
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/frb2-watchdog/frb2-watchdog.cpp
@@ -0,0 +1,258 @@
+/* Copyright 2018 Intel
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <fcntl.h>
+#include <stdlib.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <boost/container/flat_set.hpp>
+#include <cassert>
+#include <cstdint>
+#include <cstring>
+#include <iostream>
+#include <memory>
+#include <optional>
+#include <phosphor-logging/log.hpp>
+#include <sdbusplus/asio/object_server.hpp>
+#include <sdbusplus/bus.hpp>
+#include <sdbusplus/bus/match.hpp>
+#include <sdbusplus/message.hpp>
+#include <sdbusplus/timer.hpp>
+#include <vector>
+#include <xyz/openbmc_project/State/Watchdog/server.hpp>
+
+void handleResponse(const boost::system::error_code &err,
+ std::size_t bytes_transferred);
+
+static int mailboxDevFd = -1;
+
+static boost::asio::io_service io;
+static auto conn = std::make_shared<sdbusplus::asio::connection>(io);
+boost::asio::ip::tcp::socket mailBoxDevSocket(io);
+boost::asio::deadline_timer pollTimer(io);
+boost::asio::posix::stream_descriptor inputDevice(io);
+
+// mailbox registre data[0:0] for FRB2 enable bit
+boost::asio::streambuf readBuf(1);
+std::string dataRead;
+
+// FRB2 watchdog timeout is 6 minutes
+static constexpr unsigned int frb2TimerIntervalMs = 360 * 1000;
+
+// mailbox device polling time interval is 2 seconds
+static constexpr unsigned int pollMs = 2000;
+
+static constexpr unsigned int frb2Started = 1;
+static constexpr unsigned int frb2Stopped = 0;
+
+// FRB2 status
+static uint8_t frb2Status = frb2Stopped;
+
+static constexpr const char *mailboxDevName = "/dev/aspeed-mbox";
+
+static constexpr const char frb2Bus[] = "xyz.openbmc_project.FRB2";
+static constexpr const char frb2Obj[] = "/xyz/openbmc_project/FRB2";
+static constexpr const char frb2Intf[] = "xyz.openbmc_project.FRB2";
+
+static constexpr char powerBus[] = "xyz.openbmc_project.Chassis.Control.Power";
+static constexpr char powerPath[] =
+ "/xyz/openbmc_project/Chassis/Control/Power0";
+static constexpr char powerIntf[] = "xyz.openbmc_project.Chassis.Control.Power";
+
+static constexpr char wdBus[] = "xyz.openbmc_project.Watchdog";
+static constexpr char wdPath[] = "/xyz/openbmc_project/watchdog/host0";
+static constexpr char wdIntf[] = "xyz.openbmc_project.State.Watchdog";
+static constexpr char propIntf[] = "org.freedesktop.DBus.Properties";
+
+typedef boost::asio::buffers_iterator<boost::asio::const_buffers_1> iterator;
+
+// check if FRB2 bit is 0x1
+std::pair<iterator, bool> matchFRB2(iterator begin, iterator end)
+{
+ unsigned char ch = 0;
+ iterator i = begin;
+
+ while (i != end)
+ {
+ ch = static_cast<unsigned char>(*i);
+ if (ch & 0x1)
+ {
+ return std::make_pair(i, true);
+ }
+ i++;
+ }
+
+ return std::make_pair(i, false);
+}
+
+static void startRead()
+{
+ boost::asio::async_read_until(inputDevice, readBuf, matchFRB2,
+ [&](const boost::system::error_code &ec,
+ std::size_t bytes_transferred) {
+ handleResponse(ec, bytes_transferred);
+ });
+}
+
+template <typename T> void setProperty(const std::string &key, const T &val)
+{
+ phosphor::logging::log<phosphor::logging::level::DEBUG>(
+ "setProperty", phosphor::logging::entry("KEY=%s", key.c_str()));
+
+ try
+ {
+ conn->async_method_call(
+ [](const boost::system::error_code &err) {
+ if (err)
+ {
+ phosphor::logging::log<phosphor::logging::level::ERR>(
+ "async_method_call error!",
+ phosphor::logging::entry(
+ "ERROR=%s",
+ boost::system::system_error(err).what()));
+ }
+ },
+ wdBus, wdPath, propIntf, "Set", wdIntf, key,
+ sdbusplus::message::variant_ns::variant<T>(val));
+ }
+ catch (sdbusplus::exception::SdBusError &e)
+ {
+ phosphor::logging::log<phosphor::logging::level::ERR>(
+ "Dbus error!", phosphor::logging::entry("ERROR=%s", e.what()));
+ }
+}
+void handleResponse(const boost::system::error_code &err,
+ std::size_t bytes_transferred)
+{
+ std::istream responseStream(&readBuf);
+ std::string response;
+ int n = 0;
+ uint64_t interval = frb2TimerIntervalMs;
+
+ std::getline(responseStream, response);
+ responseStream.clear();
+
+ if (err == boost::system::errc::bad_file_descriptor)
+ {
+
+ phosphor::logging::log<phosphor::logging::level::DEBUG>(
+ "bad file descriptor");
+ return; // we're being destroyed
+ }
+
+ if (!err)
+ {
+ // FRB2 is set by BIOS
+ if (frb2Stopped == frb2Status)
+ {
+ // start FRB2 watchdog
+ frb2Status = frb2Started;
+ phosphor::logging::log<phosphor::logging::level::DEBUG>(
+ "FRB2 enable, start FRB2 watchdog");
+ setProperty(
+ "ExpireAction",
+ std::string(
+ "xyz.openbmc_project.State.Watchdog.Action.HardReset"));
+ setProperty("Interval", interval);
+ setProperty("TimeRemaining", interval);
+ setProperty("Initialized", true);
+ setProperty("Enabled", true);
+ }
+ }
+ else if (err == boost::asio::error::misc_errors::not_found)
+ {
+ // FRB2 is clear, stop FRB2 watchdog if it is started
+ if (frb2Started == frb2Status)
+ {
+ frb2Status = frb2Stopped;
+ phosphor::logging::log<phosphor::logging::level::DEBUG>(
+ "FRB2 is unset, stop FRB2 watchdog");
+ setProperty("Enabled", false);
+ }
+ }
+ else
+ {
+ phosphor::logging::log<phosphor::logging::level::ERR>(
+ "handleResponse error!",
+ phosphor::logging::entry("ERROR=%s",
+ boost::system::system_error(err).what()));
+ }
+
+ pollTimer.expires_from_now(boost::posix_time::milliseconds(pollMs));
+ pollTimer.async_wait(
+ [](const boost::system::error_code &ec) { startRead(); });
+}
+
+int main(int argc, char **argv)
+{
+ phosphor::logging::log<phosphor::logging::level::DEBUG>(
+ "Monitor FRB2 signal");
+
+ sdbusplus::bus::match_t biosPostSignal(
+ static_cast<sdbusplus::bus::bus &>(*conn),
+ sdbusplus::bus::match::rules::type::signal() +
+ sdbusplus::bus::match::rules::member("PostCompleted") +
+ sdbusplus::bus::match::rules::path(powerPath) +
+ sdbusplus::bus::match::rules::interface(powerIntf),
+ [](sdbusplus::message::message &msg) {
+ uint8_t value = 0;
+ ssize_t rc = 0;
+ phosphor::logging::log<phosphor::logging::level::INFO>(
+ "BIOS post completed signal");
+ // stop FRB2 and clean mailbox
+ value = 0;
+ rc = ::pwrite(mailboxDevFd, &value, 1, 0);
+ if (rc != 1)
+ {
+ phosphor::logging::log<phosphor::logging::level::ERR>(
+ "mailbox write error!");
+ }
+ setProperty("Enabled", false);
+ frb2Status = frb2Stopped;
+ return;
+ });
+
+ conn->request_name(frb2Bus);
+
+ auto server = sdbusplus::asio::object_server(conn);
+
+ std::shared_ptr<sdbusplus::asio::dbus_interface> frb2Iface =
+ server.add_interface(frb2Obj, frb2Intf);
+
+ frb2Iface->register_property("frb2Status", frb2Status);
+
+ frb2Iface->initialize();
+
+ mailboxDevFd = ::open(mailboxDevName, O_RDWR | O_CLOEXEC);
+ if (mailboxDevFd < 0)
+ {
+ phosphor::logging::log<phosphor::logging::level::ERR>(
+ "mailbox device open fail!");
+ return -1;
+ }
+
+ inputDevice.assign(mailboxDevFd);
+
+ startRead();
+
+ io.run();
+
+ ::close(mailboxDevFd);
+
+ return 0;
+}
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/phosphor-watchdog/obmc-enable-host-watchdog@.service b/meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/phosphor-watchdog/obmc-enable-host-watchdog@.service
new file mode 100644
index 000000000..87a662f7c
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/phosphor-watchdog/obmc-enable-host-watchdog@.service
@@ -0,0 +1,14 @@
+[Unit]
+Description=Start FRB2 Watchdog%i
+Wants=obmc-host-started@%i.target
+After=obmc-host-started@%i.target
+Wants=mapper-wait@-xyz-openbmc_project-watchdog-host%i.service
+After=mapper-wait@-xyz-openbmc_project-watchdog-host%i.service
+Conflicts=obmc-host-stop@%i.target
+ConditionPathExists=!/run/openbmc/host@%i-on
+
+[Service]
+Restart=always
+ExecStart=/usr/bin/env frb2-watchdog
+ExecStopPost=/bin/sh -c "busctl call `mapper get-service /xyz/openbmc_project/watchdog/host%i` /xyz/openbmc_project/watchdog/host%i org.freedesktop.DBus.Properties Set ssv xyz.openbmc_project.State.Watchdog Enabled b false"
+SyslogIdentifier=obmc-enable-host-watchdog
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/phosphor-watchdog_%.bbappend b/meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/phosphor-watchdog_%.bbappend
new file mode 100644
index 000000000..d1888e86f
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/phosphor-watchdog_%.bbappend
@@ -0,0 +1,4 @@
+FILESEXTRAPATHS_append := ":${THISDIR}/${PN}"
+
+# Remove the override to keep service running after DC cycle
+SYSTEMD_OVERRIDE_${PN}_remove = "poweron.conf:phosphor-watchdog@poweron.service.d/poweron.conf"
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/system-watchdog.bb b/meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/system-watchdog.bb
new file mode 100644
index 000000000..5da053f1d
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/system-watchdog.bb
@@ -0,0 +1,13 @@
+SUMMARY = "System watchdog"
+DESCRIPTION = "BMC hardware watchdog service that is used to reset BMC \
+ when unrecoverable events occurs"
+
+inherit allarch
+inherit obmc-phosphor-systemd
+
+LICENSE = "Apache-2.0"
+LIC_FILES_CHKSUM = "file://${INTELBASE}/COPYING.apache-2.0;md5=34400b68072d710fecd0a2940a0d1658"
+
+SYSTEMD_SERVICE_${PN} += "system-watchdog.service"
+SYSTEMD_ENVIRONMENT_FILE_${PN} += "obmc/system-watchdog/system-watchdog.conf"
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/system-watchdog/obmc/system-watchdog/system-watchdog.conf b/meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/system-watchdog/obmc/system-watchdog/system-watchdog.conf
new file mode 100644
index 000000000..defe830a1
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/system-watchdog/obmc/system-watchdog/system-watchdog.conf
@@ -0,0 +1,3 @@
+TIMEOUT=60
+INTERVAL=10
+DEVICE=/dev/watchdog1
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/system-watchdog/system-watchdog.service b/meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/system-watchdog/system-watchdog.service
new file mode 100644
index 000000000..1564fda20
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/system-watchdog/system-watchdog.service
@@ -0,0 +1,11 @@
+[Unit]
+Description=BMC Hardware Watchdog Daemon
+
+[Service]
+EnvironmentFile=/etc/default/obmc/system-watchdog/system-watchdog.conf
+ExecStart=/sbin/watchdog -T ${{TIMEOUT}} -t ${{INTERVAL}} -F ${{DEVICE}}
+KillSignal=SIGKILL
+
+[Install]
+WantedBy=basic.target
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/webui/phosphor-webui/0001-Implement-KVM-in-webui.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/webui/phosphor-webui/0001-Implement-KVM-in-webui.patch
new file mode 100644
index 000000000..a584c473c
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/webui/phosphor-webui/0001-Implement-KVM-in-webui.patch
@@ -0,0 +1,242 @@
+From a129c4e92eebd03772e5f68a2fcf855e00874f19 Mon Sep 17 00:00:00 2001
+From: Ed tanous <ed@tanous.net>
+Date: Sun, 22 Apr 2018 10:53:28 -0700
+Subject: [PATCH] Implement KVM in webui
+
+This patchset adds the infrastructure to allow KVM sessions
+through the webui. A websocket capable VNC/RFB connection
+on the BMC is needed for KVM sessions.
+
+To access, navigate to Server control -> KVM.
+
+Tested: Ran obmc-ikvm on the BMC, added a KVM Handler to
+ Phosphor Rest Server, and was able to establish a
+ KVM session in the webui on a Witherspoon.
+Change-Id: I7dda5bec41d270ae8d0913697714d4df4ec3a257
+Signed-off-by: Ed Tanous <ed.tanous@intel.com>
+Signed-off-by: Gunnar Mills <gmills@us.ibm.com>
+---
+ app/common/directives/app-navigation.html | 12 +++--
+ app/index.js | 1 +
+ app/server-control/controllers/kvm-controller.html | 5 ++
+ app/server-control/controllers/kvm-controller.js | 55 ++++++++++++++++++++++
+ app/server-control/index.js | 5 ++
+ app/server-control/styles/index.scss | 1 +
+ app/server-control/styles/kvm.scss | 11 +++++
+ package-lock.json | 5 ++
+ package.json | 5 +-
+ webpack.config.js | 6 ++-
+ 10 files changed, 98 insertions(+), 8 deletions(-)
+ create mode 100644 app/server-control/controllers/kvm-controller.html
+ create mode 100644 app/server-control/controllers/kvm-controller.js
+ create mode 100644 app/server-control/styles/kvm.scss
+
+diff --git a/app/common/directives/app-navigation.html b/app/common/directives/app-navigation.html
+index 2f3ded76cad2..f8b5db742acc 100644
+--- a/app/common/directives/app-navigation.html
++++ b/app/common/directives/app-navigation.html
+@@ -85,19 +85,21 @@
+ <a href="#/server-control/bmc-reboot" tabindex="12" ng-click="closeSubnav()">Reboot BMC</a></li>
+ <li ng-class="{'active': (path == '/server-control/remote-console')}">
+ <a href="#/server-control/remote-console" tabindex="13" ng-click="closeSubnav()">Serial over LAN console</a></li>
++ <li ng-class="{'active': (path == '/server-control/kvm')}">
++ <a href="#/server-control/kvm" tabindex="14" ng-click="closeSubnav()">KVM</a></li>
+ </ul>
+ <ul class="nav__second-level btn-firmware" ng-style="navStyle" ng-class="{opened: (showSubMenu && firstLevel == 'configuration')}">
+ <li ng-class="{'active': (path == '/configuration' || path == '/configuration/network')}">
+- <a href="#/configuration/network" tabindex="14" ng-click="closeSubnav()">Network settings</a></li>
++ <a href="#/configuration/network" tabindex="15" ng-click="closeSubnav()">Network settings</a></li>
+ <li ng-class="{'active': (path == '/configuration' || path == '/configuration/snmp')}">
+- <a href="#/configuration/snmp" tabindex="15" ng-click="closeSubnav()">SNMP settings</a></li>
++ <a href="#/configuration/snmp" tabindex="16" ng-click="closeSubnav()">SNMP settings</a></li>
+ <li ng-class="{'active': (path == '/configuration' || path == '/configuration/firmware')}">
+- <a href="#/configuration/firmware" tabindex="16" ng-click="closeSubnav()">Firmware</a></li>
++ <a href="#/configuration/firmware" tabindex="17" ng-click="closeSubnav()">Firmware</a></li>
+ <li ng-class="{'active': (path == '/configuration' || path == '/configuration/date-time')}">
+- <a href="#/configuration/date-time" tabindex="17" ng-click="closeSubnav()">Date and time settings</a></li>
++ <a href="#/configuration/date-time" tabindex="18" ng-click="closeSubnav()">Date and time settings</a></li>
+ </ul>
+ <ul class="nav__second-level btn-users" ng-style="navStyle" ng-class="{opened: (showSubMenu && firstLevel == 'users')}">
+ <li ng-class="{'active': (path == '/users' || path == '/users/manage-accounts')}">
+- <a href="#/users/manage-accounts" tabindex="18" ng-click="closeSubnav()">Manage user accounts</a></li>
++ <a href="#/users/manage-accounts" tabindex="19" ng-click="closeSubnav()">Manage user account</a></li>
+ </ul>
+ </nav>
+diff --git a/app/index.js b/app/index.js
+index c9fed83fe4a9..d6b4a08fa5c6 100644
+--- a/app/index.js
++++ b/app/index.js
+@@ -69,6 +69,7 @@ import power_operations_controller from './server-control/controllers/power-oper
+ import power_usage_controller from './server-control/controllers/power-usage-controller.js';
+ import remote_console_window_controller from './server-control/controllers/remote-console-window-controller.js';
+ import server_led_controller from './server-control/controllers/server-led-controller.js';
++import kvm_controller from './server-control/controllers/kvm-controller.js';
+
+ import server_health_index from './server-health/index.js';
+ import inventory_overview_controller from './server-health/controllers/inventory-overview-controller.js';
+diff --git a/app/server-control/controllers/kvm-controller.html b/app/server-control/controllers/kvm-controller.html
+new file mode 100644
+index 000000000000..40e4d97454bc
+--- /dev/null
++++ b/app/server-control/controllers/kvm-controller.html
+@@ -0,0 +1,5 @@
++<div id="noVNC_container">
++ <div id="noVNC_status_bar">
++ <div id="noVNC_left_dummy_elem"></div>
++ </div>
++</div>
+diff --git a/app/server-control/controllers/kvm-controller.js b/app/server-control/controllers/kvm-controller.js
+new file mode 100644
+index 000000000000..a43f169ddf19
+--- /dev/null
++++ b/app/server-control/controllers/kvm-controller.js
+@@ -0,0 +1,55 @@
++/**
++ * Controller for KVM (Kernel-based Virtual Machine)
++ *
++ * @module app/serverControl
++ * @exports kvmController
++ * @name kvmController
++ */
++
++import RFB from '@novnc/novnc/core/rfb.js';
++
++window.angular && (function(angular) {
++ 'use strict';
++
++ angular.module('app.serverControl').controller('kvmController', [
++ '$scope', '$location', '$log',
++ function($scope, $location, $log) {
++ var rfb;
++
++ $scope.$on('$destroy', function() {
++ if (rfb) {
++ rfb.disconnect();
++ }
++ });
++
++ function sendCtrlAltDel() {
++ rfb.sendCtrlAltDel();
++ return false;
++ };
++
++ function connected(e) {
++ $log.debug('RFB Connected');
++ }
++ function disconnected(e) {
++ $log.debug('RFB disconnected');
++ }
++
++ var host = $location.host();
++ var port = $location.port();
++ var target =
++ angular.element(document.querySelector('#noVNC_container'))[0];
++
++ try {
++ rfb = new RFB(target, 'wss://' + host + ':' + port + '/kvm/0', {});
++
++ rfb.addEventListener('connect', connected);
++ rfb.addEventListener('disconnect', disconnected);
++ } catch (exc) {
++ $log.error(exc);
++ updateState(
++ null, 'fatal', null, 'Unable to create RFB client -- ' + exc);
++ return; // don't continue trying to connect
++ };
++ }
++ ]);
++})(angular);
+diff --git a/app/server-control/index.js b/app/server-control/index.js
+index 739bd1eb8ad9..1b8aad50b702 100644
+--- a/app/server-control/index.js
++++ b/app/server-control/index.js
+@@ -48,6 +48,11 @@ window.angular && (function(angular) {
+ 'controller': 'remoteConsoleWindowController',
+ authenticated: true
+ })
++ .when('/server-control/kvm', {
++ 'template': require('./controllers/kvm-controller.html'),
++ 'controller': 'kvmController',
++ authenticated: true
++ })
+ .when('/server-control', {
+ 'template':
+ require('./controllers/power-operations-controller.html'),
+diff --git a/app/server-control/styles/index.scss b/app/server-control/styles/index.scss
+index f6b15ab6afc9..5e8a99580894 100644
+--- a/app/server-control/styles/index.scss
++++ b/app/server-control/styles/index.scss
+@@ -3,3 +3,4 @@
+ @import "./remote-console.scss";
+ @import "./server-led.scss";
+ @import "./power-usage.scss";
++@import "./kvm.scss";
+diff --git a/app/server-control/styles/kvm.scss b/app/server-control/styles/kvm.scss
+new file mode 100644
+index 000000000000..2f9e2c0c9f37
+--- /dev/null
++++ b/app/server-control/styles/kvm.scss
+@@ -0,0 +1,11 @@
++
++.noNVC_shown {
++ display: inline;
++}
++.noVNC_hidden {
++ display: none;
++}
++
++#noVNC_left_dummy_elem {
++ flex: 1;
++}
+diff --git a/package-lock.json b/package-lock.json
+index 2d9d31b21968..103c9b84b933 100644
+--- a/package-lock.json
++++ b/package-lock.json
+@@ -807,6 +807,11 @@
+ "to-fast-properties": "2.0.0"
+ }
+ },
++ "@novnc/novnc": {
++ "version": "1.0.0",
++ "resolved": "https://registry.npmjs.org/@novnc/novnc/-/novnc-1.0.0.tgz",
++ "integrity": "sha1-drDonm+HOMqBVBlbr1uOaoC8kQU="
++ },
+ "@types/node": {
+ "version": "10.12.18",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.18.tgz",
+diff --git a/package.json b/package.json
+index 35c6b78e320c..c0125a0b72fd 100644
+--- a/package.json
++++ b/package.json
+@@ -28,8 +28,9 @@
+ "node"
+ ],
+ "dependencies": {
+- "angular": "^1.7.5",
+- "angular-animate": "^1.7.5",
++ "@novnc/novnc": "^1.0.0",
++ "angular": "^1.7.3",
++ "angular-animate": "^1.7.3",
+ "angular-clipboard": "^1.6.2",
+ "angular-cookies": "^1.7.5",
+ "angular-messages": "^1.7.6",
+diff --git a/webpack.config.js b/webpack.config.js
+index 91cbea8f2952..6c8667cbbc98 100644
+--- a/webpack.config.js
++++ b/webpack.config.js
+@@ -113,7 +113,11 @@ module.exports = (env, options) => {
+ 'base-uri': '\'self\'',
+ 'object-src': '\'none\'',
+ 'script-src': ['\'self\''],
+- 'style-src': ['\'self\'']
++ 'style-src': ['\'self\''],
++ // KVM requires image buffers from data: payloads, so allow that in
++ // img-src
++ // https://stackoverflow.com/questions/18447970/content-security-policy-data-not-working-for-base64-images-in-chrome-28
++ 'img-src': ['\'self\'', 'data:'],
+ }),
+ new MiniCssExtractPlugin(),
+
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/webui/phosphor-webui_%.bbappend b/meta-openbmc-mods/meta-common/recipes-phosphor/webui/phosphor-webui_%.bbappend
new file mode 100644
index 000000000..e40b5ed8e
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/webui/phosphor-webui_%.bbappend
@@ -0,0 +1,3 @@
+FILESEXTRAPATHS_append := ":${THISDIR}/${PN}"
+
+SRC_URI += "file://0001-Implement-KVM-in-webui.patch"