summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjmbills <42755197+jmbills@users.noreply.github.com>2020-09-23 19:08:01 +0300
committerGitHub <noreply@github.com>2020-09-23 19:08:01 +0300
commit0db3af3120d3d4c8a3945da3e74d4521c21c7359 (patch)
tree18d6cc15665dd2a3cf3ffbdf72cc3aabedc1ba1b
parentc16fb8893b19075db4bcf3b5bf33c1db8c3ca2bd (diff)
parent5d3fc64c142786581d792d145231c835afbcdded (diff)
downloadopenbmc-0db3af3120d3d4c8a3945da3e74d4521c21c7359.tar.xz
Merge pull request #49 from Intel-BMC/update
Update to internal 0.74-57
-rw-r--r--meta-openbmc-mods/meta-ast2500/recipes-phosphor/configuration/entity-manager/WC-Baseboard.json31
-rw-r--r--meta-openbmc-mods/meta-ast2500/recipes-phosphor/configuration/entity-manager/WC-Chassis.json6
-rw-r--r--meta-openbmc-mods/meta-common/classes/obmc-phosphor-full-fitimage.bbclass43
-rw-r--r--meta-openbmc-mods/meta-common/classes/obmc-phosphor-image-common.bbclass4
-rw-r--r--meta-openbmc-mods/meta-common/classes/systemd-watchdog.bbclass8
-rw-r--r--meta-openbmc-mods/meta-common/recipes-core/crashdump/crashdump_git.bb2
-rw-r--r--meta-openbmc-mods/meta-common/recipes-core/host-error-monitor/host-error-monitor_%.bbappend2
-rw-r--r--meta-openbmc-mods/meta-common/recipes-core/ipmi/intel-ipmi-oem/0001-Fix-cold-redundancy-is-not-runing-as-user-configurat.patch121
-rw-r--r--meta-openbmc-mods/meta-common/recipes-core/ipmi/intel-ipmi-oem/0002-GetFwVersionInfo-Fix-for-Firmware-aux-version.patch120
-rw-r--r--meta-openbmc-mods/meta-common/recipes-core/ipmi/intel-ipmi-oem/0003-storagecommands-Fix-for-GetFruAreaInfo-command.patch48
-rw-r--r--meta-openbmc-mods/meta-common/recipes-core/ipmi/intel-ipmi-oem/0004-firmware-update-Add-Support-to-get-fwSecurityVer.patch111
-rw-r--r--meta-openbmc-mods/meta-common/recipes-core/ipmi/intel-ipmi-oem_%.bbappend9
-rw-r--r--meta-openbmc-mods/meta-common/recipes-core/nv-sync/nv-sync/nv-sync.service6
-rw-r--r--meta-openbmc-mods/meta-common/recipes-core/nv-sync/nv-sync/nv-syncd32
-rw-r--r--meta-openbmc-mods/meta-common/recipes-core/nv-sync/nv-sync_git.bb5
-rw-r--r--meta-openbmc-mods/meta-common/recipes-graphics/obmc-ikvm/obmc-ikvm/0005-Refine-HID-report-writing-logic.patch295
-rw-r--r--meta-openbmc-mods/meta-common/recipes-graphics/obmc-ikvm/obmc-ikvm_%.bbappend1
-rw-r--r--meta-openbmc-mods/meta-common/recipes-intel/intel-pfr/pfr-manager_%.bbappend2
-rw-r--r--meta-openbmc-mods/meta-common/recipes-intel/nic/enable-nics/enable-nics.service1
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0113-hwmon-peci-PCS-utils.patch706
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0114-hwmon-peci-cpupower-extension.patch708
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0115-hwmon-peci-dimmpower-implementation.patch677
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2019-19770/0001-blktrace-fix-debugfs-use-after-free.patch214
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2020-14356/0001-cgroup-fix-cgroup_sk_alloc-for-sk_clone_lock.patch178
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2020-14356/0002-cgroup-Fix-sock_cgroup_data-on-big-endian.patch39
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2020-16166/0001-random32-update-the-net-random-state-on-interrupt-an.patch116
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed_%.bbappend22
-rw-r--r--meta-openbmc-mods/meta-common/recipes-network/network/ncsi-monitor.bb25
-rwxr-xr-xmeta-openbmc-mods/meta-common/recipes-network/network/ncsi-monitor/check-for-host-in-reset65
-rw-r--r--meta-openbmc-mods/meta-common/recipes-network/network/ncsi-monitor/ncsi-monitor.service11
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/beepcode-mgr/files/beepcode_mgr.cpp6
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0005-EventService-https-client-support.patch390
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0007-cpudimm-get-cpu-details-from-Redfish.patch231
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0008-systems-Fix-for-Processor-Summary-Model.patch138
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0009-Fix-MetricReportDefinitions-filter-not-working.patch112
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0009-Workaround-Fix-memory-leak.patch33
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0010-Fix-EventService-stops-sending-events.patch67
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0011-Deallocate-memory-during-failed-case.patch32
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0012-System-Replace-chassis-name-in-Redfish.patch64
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0013-url_view-throws-if-a-parse-error-is-found.patch54
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0014-add-sufficient-delay-to-create-fw-update-object.patch44
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0015-Add-firmware-activation-messages-to-the-registry.patch72
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0016-EventService-Fix-type-mismatch-in-MetricReport.patch (renamed from meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0006-Fix-MetricReport-timestamp-for-EventService.patch)23
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0017-Add-MutualExclusiveProperties-registry.patch151
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0018-Add-sse-event-sequence-number.patch74
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0019-EventService-Limit-SSE-connections-as-per-design.patch108
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0020-EventService-Validate-SSE-query-filters.patch262
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb_%.bbappend16
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0064-transporthandler-Fix-for-invalid-VLAN-id.patch94
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0065-apphandler-Fix-for-set-system-Info-parameter-cmd.patch98
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0066-apphandler-Fix-for-total-session-slots-count.patch64
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0067-Fix-for-get-Channel-Info-cmd-for-reserved-channels.patch61
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0068-Removal-of-OEM-privilege-setting-for-User.patch43
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0069-apphandler-Fix-for-get-system-info-command.patch89
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0070-minor-fix-corrected-cc-for-get-channel-access.patch39
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0071-chassishandler-SetSystemBootOptions-to-new-API.patch821
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0072-chassishandler-GetSystemBootOptions-to-new-API.patch429
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host_%.bbappend9
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-net/0009-Add-dbus-interface-for-sol-commands.patch36
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-net_%.bbappend2
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/sensors/dbus-sensors_%.bbappend2
-rw-r--r--meta-openbmc-mods/meta-wht/recipes-core/host-error-monitor/host-error-monitor/0002-Add-a-workaround-for-spurious-CPU-errors.patch133
-rw-r--r--meta-openbmc-mods/meta-wht/recipes-core/host-error-monitor/host-error-monitor/0003-Override-crashdump-timeout-to-30-minutes.patch41
-rw-r--r--meta-openbmc-mods/meta-wht/recipes-core/host-error-monitor/host-error-monitor_%.bbappend2
64 files changed, 7244 insertions, 204 deletions
diff --git a/meta-openbmc-mods/meta-ast2500/recipes-phosphor/configuration/entity-manager/WC-Baseboard.json b/meta-openbmc-mods/meta-ast2500/recipes-phosphor/configuration/entity-manager/WC-Baseboard.json
index 83e6deabe..34a38489e 100644
--- a/meta-openbmc-mods/meta-ast2500/recipes-phosphor/configuration/entity-manager/WC-Baseboard.json
+++ b/meta-openbmc-mods/meta-ast2500/recipes-phosphor/configuration/entity-manager/WC-Baseboard.json
@@ -499,96 +499,112 @@
{
"BindConnector": "System Fan connector 1",
"Index": 0,
+ "MaxReading": 8000,
"Name": "Fan 1a",
"Type": "AspeedFan"
},
{
"BindConnector": "System Fan connector 1",
"Index": 1,
+ "MaxReading": 8000,
"Name": "Fan 1b",
"Type": "AspeedFan"
},
{
"BindConnector": "System Fan connector 2",
"Index": 2,
+ "MaxReading": 8000,
"Name": "Fan 2a",
"Type": "AspeedFan"
},
{
"BindConnector": "System Fan connector 2",
"Index": 3,
+ "MaxReading": 8000,
"Name": "Fan 2b",
"Type": "AspeedFan"
},
{
"BindConnector": "System Fan connector 3",
"Index": 4,
+ "MaxReading": 8000,
"Name": "Fan 3a",
"Type": "AspeedFan"
},
{
"BindConnector": "System Fan connector 3",
"Index": 5,
+ "MaxReading": 8000,
"Name": "Fan 3b",
"Type": "AspeedFan"
},
{
"BindConnector": "System Fan connector 4",
"Index": 6,
+ "MaxReading": 8000,
"Name": "Fan 4a",
"Type": "AspeedFan"
},
{
"BindConnector": "System Fan connector 4",
"Index": 7,
+ "MaxReading": 8000,
"Name": "Fan 4b",
"Type": "AspeedFan"
},
{
"BindConnector": "System Fan connector 5",
"Index": 8,
+ "MaxReading": 8000,
"Name": "Fan 5a",
"Type": "AspeedFan"
},
{
"BindConnector": "System Fan connector 5",
"Index": 9,
+ "MaxReading": 8000,
"Name": "Fan 5b",
"Type": "AspeedFan"
},
{
"BindConnector": "System Fan connector 6",
"Index": 10,
+ "MaxReading": 8000,
"Name": "Fan 6a",
"Type": "AspeedFan"
},
{
"BindConnector": "System Fan connector 6",
"Index": 11,
+ "MaxReading": 8000,
"Name": "Fan 6b",
"Type": "AspeedFan"
},
{
"BindConnector": "System Fan connector 7",
"Index": 12,
+ "MaxReading": 8000,
"Name": "Fan 7a",
"Type": "AspeedFan"
},
{
"BindConnector": "System Fan connector 7",
"Index": 13,
+ "MaxReading": 8000,
"Name": "Fan 7b",
"Type": "AspeedFan"
},
{
"BindConnector": "System Fan connector 8",
"Index": 14,
+ "MaxReading": 8000,
"Name": "Fan 8a",
"Type": "AspeedFan"
},
{
"BindConnector": "System Fan connector 8",
"Index": 15,
+ "MaxReading": 8000,
"Name": "Fan 8b",
"Type": "AspeedFan"
},
@@ -1668,6 +1684,11 @@
"Type": "PSUPresence"
},
{
+ "RedundantCount": 1,
+ "Name": "Power Unit Redundancy",
+ "Type": "PURedundancy"
+ },
+ {
"Class": "temp",
"FFGainCoefficient": 0.0,
"FFOffCoefficient": 0.0,
@@ -1951,7 +1972,7 @@
"Outputs": [],
"PCoefficient": -0.15,
"PositiveHysteresis": 0.0,
- "SetPoint": 80.0,
+ "SetPoint": 60.0,
"SlewNeg": -1,
"SlewPos": 0.0,
"Type": "Pid",
@@ -1977,7 +1998,7 @@
"Outputs": [],
"PCoefficient": -0.15,
"PositiveHysteresis": 0.0,
- "SetPoint": 80.0,
+ "SetPoint": 60.0,
"SlewNeg": -1,
"SlewPos": 0.0,
"Type": "Pid",
@@ -2002,7 +2023,7 @@
"Outputs": [],
"PCoefficient": -0.15,
"PositiveHysteresis": 0.0,
- "SetPoint": 80.0,
+ "SetPoint": 60.0,
"SlewNeg": -1,
"SlewPos": 0.0,
"Type": "Pid",
@@ -2028,7 +2049,7 @@
"Outputs": [],
"PCoefficient": -0.15,
"PositiveHysteresis": 0.0,
- "SetPoint": 80.0,
+ "SetPoint": 60.0,
"SlewNeg": -1,
"SlewPos": 0.0,
"Type": "Pid",
@@ -2451,4 +2472,4 @@
"ProductId": 145
},
"xyz.openbmc_project.Inventory.Item.System": {}
-} \ No newline at end of file
+}
diff --git a/meta-openbmc-mods/meta-ast2500/recipes-phosphor/configuration/entity-manager/WC-Chassis.json b/meta-openbmc-mods/meta-ast2500/recipes-phosphor/configuration/entity-manager/WC-Chassis.json
index 12c2e6084..ad10d87a4 100644
--- a/meta-openbmc-mods/meta-ast2500/recipes-phosphor/configuration/entity-manager/WC-Chassis.json
+++ b/meta-openbmc-mods/meta-ast2500/recipes-phosphor/configuration/entity-manager/WC-Chassis.json
@@ -3,6 +3,7 @@
{
"BindConnector": "System Fan connector 1",
"Index": 0,
+ "MaxReading": 21000,
"Name": "Fan 1",
"Thresholds": [
{
@@ -23,6 +24,7 @@
{
"BindConnector": "System Fan connector 2",
"Index": 2,
+ "MaxReading": 21000,
"Name": "Fan 2",
"Thresholds": [
{
@@ -43,6 +45,7 @@
{
"BindConnector": "System Fan connector 3",
"Index": 4,
+ "MaxReading": 21000,
"Name": "Fan 3",
"Thresholds": [
{
@@ -63,6 +66,7 @@
{
"BindConnector": "System Fan connector 6",
"Index": 10,
+ "MaxReading": 21000,
"Name": "Fan 4",
"Thresholds": [
{
@@ -83,6 +87,7 @@
{
"BindConnector": "System Fan connector 7",
"Index": 12,
+ "MaxReading": 21000,
"Name": "Fan 5",
"Thresholds": [
{
@@ -103,6 +108,7 @@
{
"BindConnector": "System Fan connector 8",
"Index": 14,
+ "MaxReading": 21000,
"Name": "Fan 6",
"Thresholds": [
{
diff --git a/meta-openbmc-mods/meta-common/classes/obmc-phosphor-full-fitimage.bbclass b/meta-openbmc-mods/meta-common/classes/obmc-phosphor-full-fitimage.bbclass
index 26c895951..0fdad5b5c 100644
--- a/meta-openbmc-mods/meta-common/classes/obmc-phosphor-full-fitimage.bbclass
+++ b/meta-openbmc-mods/meta-common/classes/obmc-phosphor-full-fitimage.bbclass
@@ -242,6 +242,7 @@ EOF
# $5 ... config ID
# $6 ... default flag
# $7 ... Hash type
+# $8 ... DTB index
fitimage_emit_section_config() {
conf_csum="${7}"
@@ -430,7 +431,7 @@ fitimage_assemble() {
if [ -n "${DTBS}" ]; then
i=1
for DTB in ${DTBS}; do
- fitimage_emit_section_config ${1} "${kernelcount}" "${DTB}" "${ramdiskcount}" "${setupcount}" "`expr ${i} = ${dtbcount}`" "${hash_type}"
+ fitimage_emit_section_config ${1} "${kernelcount}" "${DTB}" "${ramdiskcount}" "${setupcount}" "`expr ${i} = ${dtbcount}`" "${hash_type}" "${i}"
i=`expr ${i} + 1`
done
fi
@@ -470,6 +471,43 @@ python do_generate_phosphor_manifest() {
fd.write('HashType=RSA-SHA256\n')
}
+# Get HEAD git hash
+def get_head_hash(codebase):
+ err = None
+ try:
+ cmd = 'git --work-tree {} --git-dir {}/.git {}'.format(codebase, codebase, "rev-parse HEAD")
+ ret, err = bb.process.run(cmd)
+ if err is not None:
+ ret += err
+ except bb.process.ExecutionError as e:
+ ret = ''
+ if e.stdout is not None:
+ ret += e.stdout
+ if e.stderr is not None:
+ ret += e.stderr
+ except Exception as e:
+ ret = str(e)
+ return ret.split("\n")[0]
+
+# Generate file 'RELEASE'
+# It contains git hash info which is required by rest of release process (release note, for example)
+python do_generate_release_metainfo() {
+ b = d.getVar('DEPLOY_DIR_IMAGE', True)
+ corebase = d.getVar('COREBASE', True)
+ intelbase = os.path.join(corebase, 'meta-openbmc-mods')
+ filename = os.path.join(b, "RELEASE")
+ version = do_get_version(d)
+
+ with open(filename, 'w') as fd:
+ fd.write('VERSION_ID={}\n'.format(version.strip('"')))
+ if os.path.exists(corebase):
+ obmc_hash = get_head_hash(corebase)
+ fd.write('COMMUNITY_HASH={}\n'.format(obmc_hash))
+ if os.path.exists(intelbase):
+ intel_hash = get_head_hash(intelbase)
+ fd.write('INTEL_HASH={}\n'.format(intel_hash))
+}
+
def get_pubkey_type(d):
return os.listdir(get_pubkey_basedir(d))[0]
@@ -521,7 +559,9 @@ do_image_fitimage_rootfs() {
tar -h -cvf "${DEPLOY_DIR_IMAGE}/${PN}-image-update-${MACHINE}-${DATETIME}.tar" MANIFEST image-u-boot image-runtime image-kernel image-rofs image-rwfs
# make a symlink
ln -sf "${PN}-image-update-${MACHINE}-${DATETIME}.tar" "${DEPLOY_DIR_IMAGE}/image-update-${MACHINE}"
+ ln -sf "${PN}-image-update-${MACHINE}-${DATETIME}.tar" "${DEPLOY_DIR_IMAGE}/OBMC-${@ do_get_version(d)}-oob.bin"
ln -sf "image-update-${MACHINE}" "${DEPLOY_DIR_IMAGE}/image-update"
+ ln -sf "image-update-${MACHINE}" "${DEPLOY_DIR_IMAGE}/OBMC-${@ do_get_version(d)}-inband.bin"
}
do_image_fitimage_rootfs[vardepsexclude] = "DATETIME"
@@ -530,3 +570,4 @@ do_image_fitimage_rootfs[depends] += " ${DEPS}"
addtask do_image_fitimage_rootfs before do_generate_auto after do_image_complete
addtask do_generate_phosphor_manifest before do_image_fitimage_rootfs after do_image_complete
+addtask do_generate_release_metainfo before do_generate_phosphor_manifest after do_image_complete
diff --git a/meta-openbmc-mods/meta-common/classes/obmc-phosphor-image-common.bbclass b/meta-openbmc-mods/meta-common/classes/obmc-phosphor-image-common.bbclass
index 3bbed738a..034f7ac70 100644
--- a/meta-openbmc-mods/meta-common/classes/obmc-phosphor-image-common.bbclass
+++ b/meta-openbmc-mods/meta-common/classes/obmc-phosphor-image-common.bbclass
@@ -47,7 +47,9 @@ IMAGE_INSTALL_append = " \
host-misc-comm-manager \
"
-IMAGE_INSTALL_append = "${@bb.utils.contains('IMAGE_FSTYPES', 'intel-pfr', 'pfr-manager', '', d)}"
+IMAGE_INSTALL_append = " ${@bb.utils.contains('IMAGE_FSTYPES', 'intel-pfr', 'pfr-manager', '', d)}"
+
+IMAGE_INSTALL_append = " ${@bb.utils.contains('IMAGE_FSTYPES', 'intel-pfr', 'ncsi-monitor', '', d)}"
# this package was flagged as a security risk
IMAGE_INSTALL_remove += " lrzsz"
diff --git a/meta-openbmc-mods/meta-common/classes/systemd-watchdog.bbclass b/meta-openbmc-mods/meta-common/classes/systemd-watchdog.bbclass
index ad49eed82..ec5209029 100644
--- a/meta-openbmc-mods/meta-common/classes/systemd-watchdog.bbclass
+++ b/meta-openbmc-mods/meta-common/classes/systemd-watchdog.bbclass
@@ -16,6 +16,14 @@ add_watchdog_confs() {
continue
fi
+ if [ "$service" = "systemd-timesyncd.service" ]; then
+ continue
+ fi
+
+ if [ "$service" = "nv-sync.service" ]; then
+ continue
+ fi
+
if cat $D/lib/systemd/system/${service} | grep oneshot > /dev/null; then
continue
fi
diff --git a/meta-openbmc-mods/meta-common/recipes-core/crashdump/crashdump_git.bb b/meta-openbmc-mods/meta-common/recipes-core/crashdump/crashdump_git.bb
index 1a1a83dce..ae6303668 100644
--- a/meta-openbmc-mods/meta-common/recipes-core/crashdump/crashdump_git.bb
+++ b/meta-openbmc-mods/meta-common/recipes-core/crashdump/crashdump_git.bb
@@ -13,7 +13,7 @@ LICENSE = "Proprietary"
LIC_FILES_CHKSUM = "file://LICENSE;md5=43c09494f6b77f344027eea0a1c22830"
SRC_URI = "git://github.com/Intel-BMC/crashdump;protocol=git"
-SRCREV = "wht-0.9"
+SRCREV = "wht-1.0"
S = "${WORKDIR}/git"
diff --git a/meta-openbmc-mods/meta-common/recipes-core/host-error-monitor/host-error-monitor_%.bbappend b/meta-openbmc-mods/meta-common/recipes-core/host-error-monitor/host-error-monitor_%.bbappend
index 869cf5f2f..c95b2c92e 100644
--- a/meta-openbmc-mods/meta-common/recipes-core/host-error-monitor/host-error-monitor_%.bbappend
+++ b/meta-openbmc-mods/meta-common/recipes-core/host-error-monitor/host-error-monitor_%.bbappend
@@ -1,5 +1,5 @@
# Enable downstream autobump
#SRC_URI = "git://github.com/openbmc/host-error-monitor"
-SRCREV = "2fbb9eadeda2ae8a77ac53346b53f2d0a72f3e74"
+SRCREV = "9a9bf9846cabf0ef4c7076776f70230e1a7b8b13"
EXTRA_OECMAKE = "-DYOCTO=1"
diff --git a/meta-openbmc-mods/meta-common/recipes-core/ipmi/intel-ipmi-oem/0001-Fix-cold-redundancy-is-not-runing-as-user-configurat.patch b/meta-openbmc-mods/meta-common/recipes-core/ipmi/intel-ipmi-oem/0001-Fix-cold-redundancy-is-not-runing-as-user-configurat.patch
new file mode 100644
index 000000000..ae5f7b7bf
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-core/ipmi/intel-ipmi-oem/0001-Fix-cold-redundancy-is-not-runing-as-user-configurat.patch
@@ -0,0 +1,121 @@
+From e45333a83822e8ccb8e3dbc1e547fbe45b8cf959 Mon Sep 17 00:00:00 2001
+From: Kuiying Wang <kuiying.wang@intel.com>
+Date: Wed, 22 Jul 2020 22:06:37 +0800
+Subject: [PATCH] Fix cold redundancy is not runing as user configuration.
+
+Cold redundancy service is not runing as user configuration.
+1. Properties are not sync between settings server and daemon.
+2. Wrong property is used to config cold redundancy enabling.
+
+Tested:
+Cold redundancy is working as user config.
+
+Change-Id: Ia0b7aa6aff65be4d86daa82616eefaea575baf5e
+Signed-off-by: Kuiying Wang <kuiying.wang@intel.com>
+---
+ src/oemcommands.cpp | 44 +++++++++-----------------------------------
+ 1 file changed, 9 insertions(+), 35 deletions(-)
+
+diff --git a/src/oemcommands.cpp b/src/oemcommands.cpp
+index 78f4f82..d2a1811 100644
+--- a/src/oemcommands.cpp
++++ b/src/oemcommands.cpp
+@@ -2060,7 +2060,7 @@ int setCRConfig(ipmi::Context::ptr ctx, const std::string& property,
+ {
+ boost::system::error_code ec;
+ ctx->bus->yield_method_call<void>(
+- ctx->yield, ec, "xyz.openbmc_project.Settings",
++ ctx->yield, ec, "xyz.openbmc_project.PSURedundancy",
+ "/xyz/openbmc_project/control/power_supply_redundancy",
+ "org.freedesktop.DBus.Properties", "Set",
+ "xyz.openbmc_project.Control.PowerSupplyRedundancy", property, value);
+@@ -2074,10 +2074,10 @@ int setCRConfig(ipmi::Context::ptr ctx, const std::string& property,
+ return 0;
+ }
+
+-int getCRConfig(ipmi::Context::ptr ctx, const std::string& property,
+- crConfigVariant& value,
+- const std::string& service = "xyz.openbmc_project.Settings",
+- std::chrono::microseconds timeout = ipmi::IPMI_DBUS_TIMEOUT)
++int getCRConfig(
++ ipmi::Context::ptr ctx, const std::string& property, crConfigVariant& value,
++ const std::string& service = "xyz.openbmc_project.PSURedundancy",
++ std::chrono::microseconds timeout = ipmi::IPMI_DBUS_TIMEOUT)
+ {
+ boost::system::error_code ec;
+ value = ctx->bus->yield_method_call<crConfigVariant>(
+@@ -2172,25 +2172,6 @@ ipmi::RspType<uint8_t> ipmiOEMSetCRConfig(ipmi::Context::ptr ctx,
+ {
+ switch (static_cast<crParameter>(parameter))
+ {
+- case crParameter::crFeature:
+- {
+- uint8_t param1;
+- if (payload.unpack(param1) || !payload.fullyUnpacked())
+- {
+- return ipmi::responseReqDataLenInvalid();
+- }
+- // ColdRedundancy Enable can only be true or flase
+- if (param1 > 1)
+- {
+- return ipmi::responseInvalidFieldRequest();
+- }
+- if (setCRConfig(ctx, "ColdRedundancyEnabled",
+- static_cast<bool>(param1)))
+- {
+- return ipmi::responseResponseError();
+- }
+- break;
+- }
+ case crParameter::rotationFeature:
+ {
+ uint8_t param1;
+@@ -2301,13 +2282,6 @@ ipmi::RspType<uint8_t> ipmiOEMSetCRConfig(ipmi::Context::ptr ctx,
+ }
+ }
+
+- // TODO Halfwidth needs to set SetInProgress
+- if (setCRConfig(ctx, "ColdRedundancyStatus",
+- std::string("xyz.openbmc_project.Control."
+- "PowerSupplyRedundancy.Status.completed")))
+- {
+- return ipmi::responseResponseError();
+- }
+ return ipmi::responseSuccess(crSetCompleted);
+ }
+
+@@ -2338,11 +2312,11 @@ ipmi::RspType<uint8_t, std::variant<uint8_t, uint32_t, std::vector<uint8_t>>>
+ {
+ case server::PowerSupplyRedundancy::Status::inProgress:
+ return ipmi::responseSuccess(parameter,
+- static_cast<uint8_t>(0));
++ static_cast<uint8_t>(1));
+
+ case server::PowerSupplyRedundancy::Status::completed:
+ return ipmi::responseSuccess(parameter,
+- static_cast<uint8_t>(1));
++ static_cast<uint8_t>(0));
+ default:
+ phosphor::logging::log<phosphor::logging::level::ERR>(
+ "Error to get valid status");
+@@ -2351,7 +2325,7 @@ ipmi::RspType<uint8_t, std::variant<uint8_t, uint32_t, std::vector<uint8_t>>>
+ }
+ case crParameter::crFeature:
+ {
+- if (getCRConfig(ctx, "ColdRedundancyEnabled", value))
++ if (getCRConfig(ctx, "PowerSupplyRedundancyEnabled", value))
+ {
+ return ipmi::responseResponseError();
+ }
+@@ -2359,7 +2333,7 @@ ipmi::RspType<uint8_t, std::variant<uint8_t, uint32_t, std::vector<uint8_t>>>
+ if (!pResponse)
+ {
+ phosphor::logging::log<phosphor::logging::level::ERR>(
+- "Error to get ColdRedundancyEnable property");
++ "Error to get PowerSupplyRedundancyEnabled property");
+ return ipmi::responseResponseError();
+ }
+
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-core/ipmi/intel-ipmi-oem/0002-GetFwVersionInfo-Fix-for-Firmware-aux-version.patch b/meta-openbmc-mods/meta-common/recipes-core/ipmi/intel-ipmi-oem/0002-GetFwVersionInfo-Fix-for-Firmware-aux-version.patch
new file mode 100644
index 000000000..514f2dde7
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-core/ipmi/intel-ipmi-oem/0002-GetFwVersionInfo-Fix-for-Firmware-aux-version.patch
@@ -0,0 +1,120 @@
+From 52a292b8dd1b5705a6e0ce8e260d3b960b2b6edb Mon Sep 17 00:00:00 2001
+From: srikanta mondal <srikantax.mondal@intel.com>
+Date: Mon, 27 Jul 2020 23:49:14 +0000
+Subject: [PATCH] GetFwVersionInfo: Fix for Firmware aux version
+
+Issue: Get Version Information return incorrect Firmware AUX version
+
+FIX: Firmware aux version was parsing incorrectly. Do the parsing by
+ correct regex pattern of BMC version.
+
+Tested:
+Verified using ipmitool raw commands
+Before fix:
+Command: ipmitool raw 0x08 0x20 // Get version Information
+Response: 01 02 00 70 01 00 00 00 00 00 00 00 00 00 00 00
+
+After fix:
+Command: ipmitool raw 0x08 0x20 // Get version Information
+Response: 02 01 00 74 0a 8a 37 78 00 00 00 00 00 00 00 00
+ 02 00 70 01 00 00 00 00 00 00 00 00 00 00 00
+
+Signed-off-by: srikanta mondal <srikantax.mondal@intel.com>
+Change-Id: I7c2baf8a0da15e3ca4db5d6f9d6de7bf739aa755
+---
+ src/firmware-update.cpp | 56 +++++++++++++++++++++++++----------------
+ 1 file changed, 35 insertions(+), 21 deletions(-)
+
+diff --git a/src/firmware-update.cpp b/src/firmware-update.cpp
+index 8c3cc94..ec1d14a 100644
+--- a/src/firmware-update.cpp
++++ b/src/firmware-update.cpp
+@@ -1,3 +1,4 @@
++#include <byteswap.h>
+ #include <ipmid/api.h>
+ #include <openssl/evp.h>
+ #include <openssl/sha.h>
+@@ -6,6 +7,7 @@
+ #include <sys/types.h>
+ #include <unistd.h>
+
++#include <appcommands.hpp>
+ #include <boost/algorithm/string.hpp>
+ #include <boost/container/flat_map.hpp>
+ #include <boost/process/child.hpp>
+@@ -836,26 +838,44 @@ ipmi::RspType<uint8_t, std::vector<fwVersionInfoType>> ipmiGetFwVersionInfo()
+ continue;
+ }
+
+- // BMC Version format: <major>.<minor>-<build bum>-<build hash>
+- std::vector<std::string> splitVer;
+- boost::split(splitVer, verStr, boost::is_any_of(".-"));
+- if (splitVer.size() < 3)
+- {
+- phosphor::logging::log<phosphor::logging::level::INFO>(
+- "Invalid Version format.",
+- phosphor::logging::entry("Version=%s", verStr.c_str()),
+- phosphor::logging::entry("PATH=%s", fwDev.second));
+- continue;
+- }
+-
+ uint8_t majorNum = 0;
+ uint8_t minorNum = 0;
+ uint32_t buildNum = 0;
+ try
+ {
+- majorNum = std::stoul(splitVer[0], nullptr, 16);
+- minorNum = std::stoul(splitVer[1], nullptr, 16);
+- buildNum = std::stoul(splitVer[2], nullptr, 16);
++ std::optional<ipmi::MetaRevision> rev =
++ ipmi::convertIntelVersion(verStr);
++ if (rev.has_value())
++ {
++ ipmi::MetaRevision revision = rev.value();
++ majorNum = revision.major % 10 + (revision.major / 10) * 16;
++ minorNum = (revision.minor > 99 ? 99 : revision.minor);
++ minorNum = minorNum % 10 + (minorNum / 10) * 16;
++ uint32_t hash = std::stoul(revision.metaHash, 0, 16);
++ hash = bswap_32(hash);
++ buildNum = (revision.buildNo & 0xFF) + (hash & 0xFFFFFF00);
++ }
++ else
++ {
++ std::vector<std::string> splitVer;
++ boost::split(splitVer, verStr, boost::is_any_of(".-"));
++ if (splitVer.size() < 3)
++ {
++ phosphor::logging::log<phosphor::logging::level::INFO>(
++ "Invalid Version format.",
++ phosphor::logging::entry("Version=%s", verStr.c_str()),
++ phosphor::logging::entry("PATH=%s", fwDev.second));
++ continue;
++ }
++ majorNum = std::stoul(splitVer[0], nullptr, 16);
++ minorNum = std::stoul(splitVer[1], nullptr, 16);
++ buildNum = std::stoul(splitVer[2], nullptr, 16);
++ }
++ // Build Timestamp - Not supported.
++ // Update Timestamp - TODO: Need to check with CPLD team.
++ fwVerInfoList.emplace_back(
++ fwVersionInfoType(static_cast<uint8_t>(fwDev.first), majorNum,
++ minorNum, buildNum, 0, 0));
+ }
+ catch (const std::exception& e)
+ {
+@@ -864,12 +884,6 @@ ipmi::RspType<uint8_t, std::vector<fwVersionInfoType>> ipmiGetFwVersionInfo()
+ phosphor::logging::entry("ERROR=%s", e.what()));
+ continue;
+ }
+-
+- // Build Timestamp - Not supported.
+- // Update Timestamp - TODO: Need to check with CPLD team.
+- fwVerInfoList.emplace_back(
+- fwVersionInfoType(static_cast<uint8_t>(fwDev.first), majorNum,
+- minorNum, buildNum, 0, 0));
+ }
+
+ return ipmi::responseSuccess(fwVerInfoList.size(), fwVerInfoList);
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-core/ipmi/intel-ipmi-oem/0003-storagecommands-Fix-for-GetFruAreaInfo-command.patch b/meta-openbmc-mods/meta-common/recipes-core/ipmi/intel-ipmi-oem/0003-storagecommands-Fix-for-GetFruAreaInfo-command.patch
new file mode 100644
index 000000000..32a170d90
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-core/ipmi/intel-ipmi-oem/0003-storagecommands-Fix-for-GetFruAreaInfo-command.patch
@@ -0,0 +1,48 @@
+From 1e2ab0613dde7d8051052eecf6f5f2381e91ce87 Mon Sep 17 00:00:00 2001
+From: Jayaprakash Mutyala <mutyalax.jayaprakash@intel.com>
+Date: Mon, 3 Aug 2020 16:57:00 +0000
+Subject: [PATCH] storagecommands: Fix for GetFruAreaInfo command
+
+Issue: GetFruAreaInfo command is giving incorrect response for Invalid
+FRU Device ID's.
+
+Fix: Add check for invalid FRU Device ID's to return completion code as
+0xCB.
+
+Tested:
+Verified using ipmitool raw commands.
+Case 1: Valid FRU Device ID:
+Command: ipmitool raw 0x0a 0x10 0xce //Get fru Area info
+Response: a9 00 00
+Case 2: Invalid FRU Device ID:
+Command: ipmitool raw 0x0a 0x10 0x01 //Get fru Area info
+Response: Unable to send RAW command (channel=0x0 netfn=0xa lun=0x0
+ cmd=0x10 rsp=0xcb): Requested sensor, data, or record not
+ found
+
+Signed-off-by: Jayaprakash Mutyala <mutyalax.jayaprakash@intel.com>
+Change-Id: I8e3416beff40c133804af9e913d83c2372784439
+---
+ src/storagecommands.cpp | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/src/storagecommands.cpp b/src/storagecommands.cpp
+index f1b98e0..bd43a34 100644
+--- a/src/storagecommands.cpp
++++ b/src/storagecommands.cpp
+@@ -538,7 +538,11 @@ ipmi::RspType<uint16_t, // inventorySize
+ return ipmi::responseInvalidFieldRequest();
+ }
+
+- getFru(ctx, fruDeviceId);
++ ipmi::Cc ret = getFru(ctx, fruDeviceId);
++ if (ret != ipmi::ccSuccess)
++ {
++ return ipmi::response(ret);
++ }
+
+ constexpr uint8_t accessType =
+ static_cast<uint8_t>(GetFRUAreaAccessType::byte);
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-core/ipmi/intel-ipmi-oem/0004-firmware-update-Add-Support-to-get-fwSecurityVer.patch b/meta-openbmc-mods/meta-common/recipes-core/ipmi/intel-ipmi-oem/0004-firmware-update-Add-Support-to-get-fwSecurityVer.patch
new file mode 100644
index 000000000..20e94b79d
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-core/ipmi/intel-ipmi-oem/0004-firmware-update-Add-Support-to-get-fwSecurityVer.patch
@@ -0,0 +1,111 @@
+From a8dd197a4b729c10d09c55ebf26ed7d0796fd261 Mon Sep 17 00:00:00 2001
+From: Punith Nadur Basavarajaiah <punitx.basavarajaiah@intel.com>
+Date: Wed, 19 Aug 2020 18:05:44 +0000
+Subject: [PATCH] firmware-update:Add Support to get fwSecurityVer
+
+Add support to read BKC and SVN version for BMC Active and Recovery
+image.
+
+Tested:
+Command : ipmitool raw 0x08 0x21 //get firmware security version
+Response: 02 01 01 01 02 01 01
+
+Signed-off-by: Punith Nadur Basavarajaiah <punitx.basavarajaiah@intel.com>
+Change-Id: I25a801fe00fef3c4c65b57aacb59089be1705d58
+---
+ src/firmware-update.cpp | 70 +++++++++++++++++++++++++++++++++++++----
+ 1 file changed, 64 insertions(+), 6 deletions(-)
+
+diff --git a/src/firmware-update.cpp b/src/firmware-update.cpp
+index ec1d14a..d27b8c6 100644
+--- a/src/firmware-update.cpp
++++ b/src/firmware-update.cpp
+@@ -72,6 +72,13 @@ static inline auto responseNotSupportedInPresentState()
+ }
+ } // namespace ipmi
+
++static constexpr size_t imageCount = 2;
++std::array<std::array<uint8_t, imageCount>, imageCount> imgFwSecurityVersion = {
++ (0, 0), (0, 0)};
++static constexpr size_t svnActiveVerOffsetInPfm = 0x404;
++static constexpr size_t bkcActiveVerOffsetInPfm = 0x405;
++static constexpr size_t svnRecoveryVerOffsetInPfm = 0x804;
++static constexpr size_t bkcRecoveryVerOffsetInPfm = 0x805;
+ static constexpr const char* bmcStateIntf = "xyz.openbmc_project.State.BMC";
+ static constexpr const char* bmcStatePath = "/xyz/openbmc_project/state/bmc0";
+ static constexpr const char* bmcStateReady =
+@@ -888,14 +895,65 @@ ipmi::RspType<uint8_t, std::vector<fwVersionInfoType>> ipmiGetFwVersionInfo()
+
+ return ipmi::responseSuccess(fwVerInfoList.size(), fwVerInfoList);
+ }
+-using fwSecurityVersionInfoType = std::tuple<uint8_t, // ID Tag
+- uint8_t, // BKC Version
+- uint8_t>; // SVN Version
+-ipmi::RspType<uint8_t, std::vector<fwSecurityVersionInfoType>>
++
++std::array<uint8_t, imageCount> getSecurityVersionInfo(const char* mtdDevBuf,
++ size_t svnVerOffsetInPfm,
++ size_t bkcVerOffsetInPfm)
++{
++ constexpr size_t bufLength = 1;
++ std::array<uint8_t, imageCount> fwSecurityVersionBuf = {0}, temp;
++ constexpr uint8_t svnIndexValue = 0x00;
++ constexpr uint8_t bkcIndexValue = 0x01;
++ constexpr uint8_t tempIndexValue = 0x00;
++ try
++ {
++ SPIDev spiDev(mtdDevBuf);
++ spiDev.spiReadData(svnVerOffsetInPfm, bufLength, temp.data());
++ fwSecurityVersionBuf.at(svnIndexValue) = temp.at(tempIndexValue);
++ spiDev.spiReadData(bkcVerOffsetInPfm, bufLength, temp.data());
++ fwSecurityVersionBuf.at(bkcIndexValue) = temp.at(tempIndexValue);
++ }
++ catch (const std::exception& e)
++ {
++ phosphor::logging::log<phosphor::logging::level::ERR>(
++ "Exception caught in getSecurityVersionInfo",
++ phosphor::logging::entry("MSG=%s", e.what()));
++ fwSecurityVersionBuf = {0, 0};
++ }
++
++ return fwSecurityVersionBuf;
++}
++
++ipmi::RspType<
++ uint8_t, // device ID
++ uint8_t, // Active Image Value
++ std::array<uint8_t, imageCount>, // Security version for Active Image
++ uint8_t, // recovery Image Value
++ std::array<uint8_t, imageCount>> // Security version for Recovery Image
+ ipmiGetFwSecurityVersionInfo()
+ {
+- // TODO: Need to add support.
+- return ipmi::responseInvalidCommand();
++ static bool cacheFlag = false;
++ constexpr std::array<const char*, imageCount> mtdDevBuf = {
++ bmcActivePfmMTDDev, bmcRecoveryImgMTDDev};
++
++ // To avoid multiple reading from SPI device
++ if (!cacheFlag)
++ {
++ imgFwSecurityVersion[0] = getSecurityVersionInfo(
++ mtdDevBuf[0], svnActiveVerOffsetInPfm, bkcActiveVerOffsetInPfm);
++ imgFwSecurityVersion[1] = getSecurityVersionInfo(
++ mtdDevBuf[1], svnRecoveryVerOffsetInPfm, bkcRecoveryVerOffsetInPfm);
++ cacheFlag = true;
++ }
++
++ constexpr uint8_t ActivePfmMTDDev = 0x00;
++ constexpr uint8_t RecoveryImgMTDDev = 0x01;
++
++ return ipmi::responseSuccess(
++ imageCount, static_cast<uint8_t>(FWDeviceIDTag::bmcActiveImage),
++ imgFwSecurityVersion[ActivePfmMTDDev],
++ static_cast<uint8_t>(FWDeviceIDTag::bmcRecoveryImage),
++ imgFwSecurityVersion[RecoveryImgMTDDev]);
+ }
+
+ ipmi::RspType<std::array<uint8_t, certKeyLen>,
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-core/ipmi/intel-ipmi-oem_%.bbappend b/meta-openbmc-mods/meta-common/recipes-core/ipmi/intel-ipmi-oem_%.bbappend
index cd2011b4a..a7486376f 100644
--- a/meta-openbmc-mods/meta-common/recipes-core/ipmi/intel-ipmi-oem_%.bbappend
+++ b/meta-openbmc-mods/meta-common/recipes-core/ipmi/intel-ipmi-oem_%.bbappend
@@ -3,3 +3,12 @@ EXTRA_OECMAKE += "${@bb.utils.contains('EXTRA_IMAGE_FEATURES', 'validation-unsec
EXTRA_OECMAKE += "-DUSING_ENTITY_MANAGER_DECORATORS=OFF"
SRC_URI = "git://github.com/openbmc/intel-ipmi-oem.git"
SRCREV = "04a38ed10db3a0203aa7804bfea6fbd69dafdde8"
+
+FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
+PROJECT_SRC_DIR := "${THISDIR}/${PN}"
+
+SRC_URI += "file://0001-Fix-cold-redundancy-is-not-runing-as-user-configurat.patch \
+ file://0002-GetFwVersionInfo-Fix-for-Firmware-aux-version.patch \
+ file://0003-storagecommands-Fix-for-GetFruAreaInfo-command.patch \
+ file://0004-firmware-update-Add-Support-to-get-fwSecurityVer.patch \
+ "
diff --git a/meta-openbmc-mods/meta-common/recipes-core/nv-sync/nv-sync/nv-sync.service b/meta-openbmc-mods/meta-common/recipes-core/nv-sync/nv-sync/nv-sync.service
index bad3329d3..4595541c6 100644
--- a/meta-openbmc-mods/meta-common/recipes-core/nv-sync/nv-sync/nv-sync.service
+++ b/meta-openbmc-mods/meta-common/recipes-core/nv-sync/nv-sync/nv-sync.service
@@ -2,10 +2,8 @@
Description=Overlay sync to NV storage
[Service]
-# Run rsync periodically to sync the overlay to NV storage
-ExecStart=bash -c 'while true; do rsync -a --delete /tmp/.overlay/ /tmp/.rwfs/.overlay; sync /tmp/.rwfs/.overlay; sleep 10; done'
-# On shutdown, archive the bash history so we don't lose it and run one last sync
-ExecStop=bash -c 'history -a; rsync -a --delete /tmp/.overlay/ /tmp/.rwfs/.overlay; sync /tmp/.rwfs/.overlay; sleep 5'
+# Run a job to periodically sync the overlay to NV storage
+ExecStart=/usr/bin/nv-syncd
# Due to sync delay stopping this service will take more than default 10 seconds
TimeoutStopSec=20
diff --git a/meta-openbmc-mods/meta-common/recipes-core/nv-sync/nv-sync/nv-syncd b/meta-openbmc-mods/meta-common/recipes-core/nv-sync/nv-sync/nv-syncd
new file mode 100644
index 000000000..e2bb4bb0c
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-core/nv-sync/nv-sync/nv-syncd
@@ -0,0 +1,32 @@
+#!/bin/bash
+
+NVMP=/tmp/.rwfs
+SOMP=/var/sofs
+
+do_sync() {
+ rsync -a --delete /tmp/.overlay/ $NVMP/.overlay
+ sync $NVMP/.overlay
+}
+
+stop_nv() {
+ history -a
+ do_sync
+ mount -o remount,ro $NVMP
+ mount -o remount,ro $SOMP
+ exit 0
+}
+
+# register cleanup function
+trap stop_nv SIGINT
+trap stop_nv SIGTERM
+trap stop_nv EXIT
+
+# make sure the mount points are RW
+mount -o remount,rw $NVMP
+mount -o remount,rw $SOMP
+
+# Run rsync periodically to sync the overlay to NV storage
+while true; do
+ do_sync
+ sleep 10
+done
diff --git a/meta-openbmc-mods/meta-common/recipes-core/nv-sync/nv-sync_git.bb b/meta-openbmc-mods/meta-common/recipes-core/nv-sync/nv-sync_git.bb
index 0ee70e880..420fc258b 100644
--- a/meta-openbmc-mods/meta-common/recipes-core/nv-sync/nv-sync_git.bb
+++ b/meta-openbmc-mods/meta-common/recipes-core/nv-sync/nv-sync_git.bb
@@ -3,6 +3,7 @@ DESCRIPTION = "Script to periodically sync the overlay to NV storage"
S = "${WORKDIR}"
SRC_URI = "file://nv-sync.service \
+ file://nv-syncd \
"
LICENSE = "Apache-2.0"
@@ -10,11 +11,15 @@ LIC_FILES_CHKSUM = "file://${INTELBASE}/COPYING.apache-2.0;md5=34400b68072d710fe
inherit systemd
+RDEPENDS_${PN} += "bash"
+
FILES_${PN} += "${systemd_system_unitdir}/nv-sync.service"
do_install() {
install -d ${D}${systemd_system_unitdir}
install -m 0644 ${WORKDIR}/nv-sync.service ${D}${systemd_system_unitdir}
+ install -d ${D}${bindir}
+ install -m 0755 ${WORKDIR}/nv-syncd ${D}${bindir}/nv-syncd
}
SYSTEMD_SERVICE_${PN} += " nv-sync.service"
diff --git a/meta-openbmc-mods/meta-common/recipes-graphics/obmc-ikvm/obmc-ikvm/0005-Refine-HID-report-writing-logic.patch b/meta-openbmc-mods/meta-common/recipes-graphics/obmc-ikvm/obmc-ikvm/0005-Refine-HID-report-writing-logic.patch
new file mode 100644
index 000000000..5293f3f27
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-graphics/obmc-ikvm/obmc-ikvm/0005-Refine-HID-report-writing-logic.patch
@@ -0,0 +1,295 @@
+From 68885eb4d056b8343c567c48ece7e875feb28fc0 Mon Sep 17 00:00:00 2001
+From: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+Date: Thu, 30 Jul 2020 00:29:19 -0700
+Subject: [PATCH] Refine HID report writing logic
+
+Blocking write on the keyboard HID device causes screen freezing
+during turning off the host power. To fix this issue, this commit
+refines the logic using non-blocking write. As a side effect,
+non-blocking write introduces event dropping when kernel HID driver
+returns -EAGAIN when the driver is in busy state so this commit also
+adds retry logic to cover the case.
+
+Tested: Didn't see the screen freezing issue.
+
+Change-Id: Ibd95f567c49f448cd053948c14c006de17c52420
+Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+---
+ ikvm_input.cpp | 106 ++++++++++++++++++++++++++++++++----------------
+ ikvm_input.hpp | 13 +++---
+ ikvm_server.cpp | 2 -
+ 3 files changed, 79 insertions(+), 42 deletions(-)
+
+diff --git a/ikvm_input.cpp b/ikvm_input.cpp
+index c4cce5088461..480db3c094bc 100644
+--- a/ikvm_input.cpp
++++ b/ikvm_input.cpp
+@@ -25,9 +25,8 @@ using namespace phosphor::logging;
+ using namespace sdbusplus::xyz::openbmc_project::Common::File::Error;
+
+ Input::Input(const std::string& kbdPath, const std::string& ptrPath) :
+- sendKeyboard(false), sendPointer(false), keyboardFd(-1), pointerFd(-1),
+- keyboardReport{0}, pointerReport{0}, keyboardPath(kbdPath),
+- pointerPath(ptrPath)
++ keyboardFd(-1), pointerFd(-1), keyboardReport{0}, pointerReport{0},
++ keyboardPath(kbdPath), pointerPath(ptrPath)
+ {
+ hidUdcStream.exceptions(std::ofstream::failbit | std::ofstream::badbit);
+ hidUdcStream.open(hidUdcPath, std::ios::out | std::ios::app);
+@@ -79,7 +78,8 @@ void Input::connect()
+
+ if (!keyboardPath.empty())
+ {
+- keyboardFd = open(keyboardPath.c_str(), O_RDWR | O_CLOEXEC);
++ keyboardFd = open(keyboardPath.c_str(),
++ O_RDWR | O_CLOEXEC | O_NONBLOCK);
+ if (keyboardFd < 0)
+ {
+ log<level::ERR>("Failed to open input device",
+@@ -135,6 +135,12 @@ void Input::keyEvent(rfbBool down, rfbKeySym key, rfbClientPtr cl)
+ {
+ Server::ClientData* cd = (Server::ClientData*)cl->clientData;
+ Input* input = cd->input;
++ bool sendKeyboard = false;
++
++ if (input->keyboardFd < 0)
++ {
++ return;
++ }
+
+ if (down)
+ {
+@@ -150,7 +156,7 @@ void Input::keyEvent(rfbBool down, rfbKeySym key, rfbClientPtr cl)
+ {
+ input->keyboardReport[i] = sc;
+ input->keysDown.insert(std::make_pair(key, i));
+- input->sendKeyboard = true;
++ sendKeyboard = true;
+ break;
+ }
+ }
+@@ -163,7 +169,7 @@ void Input::keyEvent(rfbBool down, rfbKeySym key, rfbClientPtr cl)
+ if (mod)
+ {
+ input->keyboardReport[0] |= mod;
+- input->sendKeyboard = true;
++ sendKeyboard = true;
+ }
+ }
+ }
+@@ -175,7 +181,7 @@ void Input::keyEvent(rfbBool down, rfbKeySym key, rfbClientPtr cl)
+ {
+ input->keyboardReport[it->second] = 0;
+ input->keysDown.erase(it);
+- input->sendKeyboard = true;
++ sendKeyboard = true;
+ }
+ else
+ {
+@@ -184,10 +190,15 @@ void Input::keyEvent(rfbBool down, rfbKeySym key, rfbClientPtr cl)
+ if (mod)
+ {
+ input->keyboardReport[0] &= ~mod;
+- input->sendKeyboard = true;
++ sendKeyboard = true;
+ }
+ }
+ }
++
++ if (sendKeyboard)
++ {
++ input->writeKeyboard(input->keyboardReport);
++ }
+ }
+
+ void Input::pointerEvent(int buttonMask, int x, int y, rfbClientPtr cl)
+@@ -197,6 +208,11 @@ void Input::pointerEvent(int buttonMask, int x, int y, rfbClientPtr cl)
+ Server* server = (Server*)cl->screen->screenData;
+ const Video& video = server->getVideo();
+
++ if (input->pointerFd < 0)
++ {
++ return;
++ }
++
+ input->pointerReport[0] = ((buttonMask & 0x4) >> 1) |
+ ((buttonMask & 0x2) << 1) | (buttonMask & 0x1);
+
+@@ -214,8 +230,8 @@ void Input::pointerEvent(int buttonMask, int x, int y, rfbClientPtr cl)
+ memcpy(&input->pointerReport[3], &yy, 2);
+ }
+
+- input->sendPointer = true;
+ rfbDefaultPtrAddEvent(buttonMask, x, y, cl);
++ input->writePointer(input->pointerReport);
+ }
+
+ void Input::sendWakeupPacket()
+@@ -249,23 +265,6 @@ void Input::sendWakeupPacket()
+ }
+ }
+
+-void Input::sendReport()
+-{
+- if (sendKeyboard && keyboardFd >= 0)
+- {
+- writeKeyboard(keyboardReport);
+-
+- sendKeyboard = false;
+- }
+-
+- if (sendPointer && pointerFd >= 0)
+- {
+- writePointer(pointerReport);
+-
+- sendPointer = false;
+- }
+-}
+-
+ uint8_t Input::keyToMod(rfbKeySym key)
+ {
+ uint8_t mod = 0;
+@@ -489,14 +488,35 @@ uint8_t Input::keyToScancode(rfbKeySym key)
+
+ bool Input::writeKeyboard(const uint8_t *report)
+ {
+- if (write(keyboardFd, report, KEY_REPORT_LENGTH) != KEY_REPORT_LENGTH)
++ std::unique_lock<std::mutex> lk(keyMutex);
++ uint retryCount = HID_REPORT_RETRY_MAX;
++
++ while (retryCount > 0)
+ {
+- if (errno != ESHUTDOWN && errno != EAGAIN)
++ if (write(keyboardFd, report, KEY_REPORT_LENGTH) == KEY_REPORT_LENGTH)
+ {
+- log<level::ERR>("Failed to write keyboard report",
+- entry("ERROR=%s", strerror(errno)));
++ break;
++ }
++
++ if (errno != EAGAIN)
++ {
++ if (errno != ESHUTDOWN)
++ {
++ log<level::ERR>("Failed to write keyboard report",
++ entry("ERROR=%s", strerror(errno)));
++ }
++
++ break;
+ }
+
++ lk.unlock();
++ std::this_thread::sleep_for(std::chrono::milliseconds(10));
++ lk.lock();
++ retryCount--;
++ }
++
++ if (!retryCount || errno)
++ {
+ return false;
+ }
+
+@@ -505,13 +525,31 @@ bool Input::writeKeyboard(const uint8_t *report)
+
+ void Input::writePointer(const uint8_t *report)
+ {
+- if (write(pointerFd, report, PTR_REPORT_LENGTH) != PTR_REPORT_LENGTH)
++ std::unique_lock<std::mutex> lk(ptrMutex);
++ uint retryCount = HID_REPORT_RETRY_MAX;
++
++ while (retryCount > 0)
+ {
+- if (errno != ESHUTDOWN && errno != EAGAIN)
++ if (write(pointerFd, report, PTR_REPORT_LENGTH) == PTR_REPORT_LENGTH)
+ {
+- log<level::ERR>("Failed to write pointer report",
+- entry("ERROR=%s", strerror(errno)));
++ break;
++ }
++
++ if (errno != EAGAIN)
++ {
++ if (errno != ESHUTDOWN)
++ {
++ log<level::ERR>("Failed to write pointer report",
++ entry("ERROR=%s", strerror(errno)));
++ }
++
++ break;
+ }
++
++ lk.unlock();
++ std::this_thread::sleep_for(std::chrono::milliseconds(10));
++ lk.lock();
++ retryCount--;
+ }
+ }
+
+diff --git a/ikvm_input.hpp b/ikvm_input.hpp
+index aae7cefbef6e..558251d673cc 100644
+--- a/ikvm_input.hpp
++++ b/ikvm_input.hpp
+@@ -5,6 +5,7 @@
+ #include <filesystem>
+ #include <fstream>
+ #include <map>
++#include <mutex>
+ #include <string>
+
+ namespace ikvm
+@@ -56,8 +57,6 @@ class Input
+
+ /* @brief Sends a wakeup data packet to the USB input device */
+ void sendWakeupPacket();
+- /* @brief Sends an HID report to the USB input device */
+- void sendReport();
+
+ private:
+ static constexpr int NUM_MODIFIER_BITS = 4;
+@@ -84,6 +83,8 @@ class Input
+ /* @brief Path to the USB virtual hub */
+ static constexpr const char* usbVirtualHubPath =
+ "/sys/bus/platform/devices/1e6a0000.usb-vhub";
++ /* @brief Retry limit for writing an HID report */
++ static constexpr int HID_REPORT_RETRY_MAX = 5;
+ /*
+ * @brief Translates a RFB-specific key code to HID modifier bit
+ *
+@@ -100,10 +101,6 @@ class Input
+ bool writeKeyboard(const uint8_t *report);
+ void writePointer(const uint8_t *report);
+
+- /* @brief Indicates whether or not to send a keyboard report */
+- bool sendKeyboard;
+- /* @brief Indicates whether or not to send a pointer report */
+- bool sendPointer;
+ /* @brief File descriptor for the USB keyboard device */
+ int keyboardFd;
+ /* @brief File descriptor for the USB mouse device */
+@@ -123,6 +120,10 @@ class Input
+ std::map<int, int> keysDown;
+ /* @brief Handle of the HID gadget UDC */
+ std::ofstream hidUdcStream;
++ /* @brief Mutex for sending keyboard reports */
++ std::mutex keyMutex;
++ /* @brief Mutex for sending pointer reports */
++ std::mutex ptrMutex;
+ };
+
+ } // namespace ikvm
+diff --git a/ikvm_server.cpp b/ikvm_server.cpp
+index 0736d1f55f73..7be99e4379d1 100644
+--- a/ikvm_server.cpp
++++ b/ikvm_server.cpp
+@@ -79,8 +79,6 @@ void Server::run()
+
+ if (server->clientHead)
+ {
+- input.sendReport();
+-
+ frameCounter++;
+ if (pendingResize && frameCounter > video.getFrameRate())
+ {
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-graphics/obmc-ikvm/obmc-ikvm_%.bbappend b/meta-openbmc-mods/meta-common/recipes-graphics/obmc-ikvm/obmc-ikvm_%.bbappend
index baa93bc04..9ea9e1a4e 100644
--- a/meta-openbmc-mods/meta-common/recipes-graphics/obmc-ikvm/obmc-ikvm_%.bbappend
+++ b/meta-openbmc-mods/meta-common/recipes-graphics/obmc-ikvm/obmc-ikvm_%.bbappend
@@ -6,4 +6,5 @@ SRCREV = "861337e8ec92767c4c88237ec5db494a2a67fa8d"
SRC_URI += " \
file://0003-Fix-keyboard-and-mouse-input-events-dropping-issue.patch \
file://0004-Connect-HID-gadget-device-dynamically.patch \
+ file://0005-Refine-HID-report-writing-logic.patch \
"
diff --git a/meta-openbmc-mods/meta-common/recipes-intel/intel-pfr/pfr-manager_%.bbappend b/meta-openbmc-mods/meta-common/recipes-intel/intel-pfr/pfr-manager_%.bbappend
index c6dd34bb1..fa5bc79af 100644
--- a/meta-openbmc-mods/meta-common/recipes-intel/intel-pfr/pfr-manager_%.bbappend
+++ b/meta-openbmc-mods/meta-common/recipes-intel/intel-pfr/pfr-manager_%.bbappend
@@ -1,5 +1,5 @@
# Enable downstream autobump
SRC_URI = "git://github.com/openbmc/pfr-manager"
-SRCREV = "53b8700fd18873cffe7ee70b2306e7c66b2f7037"
+SRCREV = "068c66db7d099b179e5588b156ba7444a5b68819"
DEPENDS += " libgpiod \
"
diff --git a/meta-openbmc-mods/meta-common/recipes-intel/nic/enable-nics/enable-nics.service b/meta-openbmc-mods/meta-common/recipes-intel/nic/enable-nics/enable-nics.service
index 531b5d86e..c1d0f602f 100644
--- a/meta-openbmc-mods/meta-common/recipes-intel/nic/enable-nics/enable-nics.service
+++ b/meta-openbmc-mods/meta-common/recipes-intel/nic/enable-nics/enable-nics.service
@@ -1,7 +1,6 @@
[Unit]
Description=Re-enable NICs mistakenly disabled by earlier BMC firmware
Wants=multi-user.target
-After=multi-user.target
[Service]
Type=oneshot
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0113-hwmon-peci-PCS-utils.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0113-hwmon-peci-PCS-utils.patch
new file mode 100644
index 000000000..6f6aab922
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0113-hwmon-peci-PCS-utils.patch
@@ -0,0 +1,706 @@
+From 44842b3fc1ceb7da68171b6b6c2f24a3b70405ed Mon Sep 17 00:00:00 2001
+From: Zbigniew Lukwinski <zbigniew.lukwinski@linux.intel.com>
+Date: Tue, 16 Jun 2020 11:34:28 +0200
+Subject: [PATCH] hwmon: peci: PCS utils
+
+1. Helpers for reading/writing PCS registers added.
+2. PECI sensor configuration structure definition and helpers added.
+3. New PECI PCS index and parameters definitions added.
+
+Tested:
+ * on WilsonCity platform
+ * hwmon/peci modules work as before the change
+
+Signed-off-by: Zbigniew Lukwinski <zbigniew.lukwinski@linux.intel.com>
+---
+ drivers/hwmon/peci-cpupower.c | 4 +-
+ drivers/hwmon/peci-hwmon.h | 557 +++++++++++++++++++++++++++++++++-
+ include/linux/mfd/intel-peci-client.h | 34 ++-
+ include/uapi/linux/peci-ioctl.h | 5 +-
+ 4 files changed, 592 insertions(+), 8 deletions(-)
+
+diff --git a/drivers/hwmon/peci-cpupower.c b/drivers/hwmon/peci-cpupower.c
+index 6907696..a3a8fc1 100644
+--- a/drivers/hwmon/peci-cpupower.c
++++ b/drivers/hwmon/peci-cpupower.c
+@@ -49,7 +49,7 @@ static int get_average_power(struct peci_cpupower *priv)
+
+ ret = peci_client_read_package_config(priv->mgr,
+ PECI_MBX_INDEX_TDP_UNITS,
+- PECI_PKG_ID_PKG_ENERGY_STATUS,
++ PECI_PKG_ID_CPU_PACKAGE,
+ pkg_cfg);
+
+ u32 power_unit = ((le32_to_cpup((__le32 *)pkg_cfg)) & 0x1f00) >> 8;
+@@ -59,7 +59,7 @@ static int get_average_power(struct peci_cpupower *priv)
+
+ ret = peci_client_read_package_config(priv->mgr,
+ PECI_MBX_INDEX_ENERGY_COUNTER,
+- PECI_PKG_ID_PKG_ENERGY_STATUS,
++ PECI_PKG_ID_CPU_PACKAGE,
+ pkg_cfg);
+ if (!ret) {
+ u32 energy_cnt = le32_to_cpup((__le32 *)pkg_cfg);
+diff --git a/drivers/hwmon/peci-hwmon.h b/drivers/hwmon/peci-hwmon.h
+index 4d78c52..b8949ae 100644
+--- a/drivers/hwmon/peci-hwmon.h
++++ b/drivers/hwmon/peci-hwmon.h
+@@ -1,20 +1,23 @@
+ /* SPDX-License-Identifier: GPL-2.0 */
+-/* Copyright (c) 2018-2019 Intel Corporation */
++/* Copyright (c) 2018-2020 Intel Corporation */
+
+ #ifndef __PECI_HWMON_H
+ #define __PECI_HWMON_H
+
+ #include <linux/peci.h>
++#include <asm/div64.h>
+
+ #define TEMP_TYPE_PECI 6 /* Sensor type 6: Intel PECI */
+-#define UPDATE_INTERVAL HZ
++#define UPDATE_INTERVAL_DEFAULT HZ
++#define UPDATE_INTERVAL_100MS (HZ / 10)
++#define UPDATE_INTERVAL_10S (HZ * 10)
+
+ #define PECI_HWMON_LABEL_STR_LEN 10
+
+ /**
+ * struct peci_sensor_data - PECI sensor information
+ * @valid: flag to indicate the sensor value is valid
+- * @value: sensor value in millidegree Celsius
++ * @value: sensor value in milli units
+ * @last_updated: time of the last update in jiffies
+ */
+ struct peci_sensor_data {
+@@ -32,7 +35,24 @@ struct peci_sensor_data {
+ static inline bool peci_sensor_need_update(struct peci_sensor_data *sensor)
+ {
+ return !sensor->valid ||
+- time_after(jiffies, sensor->last_updated + UPDATE_INTERVAL);
++ time_after(jiffies, sensor->last_updated +
++ UPDATE_INTERVAL_DEFAULT);
++}
++
++/**
++ * peci_sensor_need_update_with_time - check whether sensor update is needed
++ * or not
++ * @sensor: pointer to sensor data struct
++ * @update_interval: update interval to check
++ *
++ * Return: true if update is needed, false if not.
++ */
++static inline bool
++peci_sensor_need_update_with_time(struct peci_sensor_data *sensor,
++ ulong update_interval)
++{
++ return !sensor->valid ||
++ time_after(jiffies, sensor->last_updated + update_interval);
+ }
+
+ /**
+@@ -45,4 +65,533 @@ static inline void peci_sensor_mark_updated(struct peci_sensor_data *sensor)
+ sensor->last_updated = jiffies;
+ }
+
++/**
++ * peci_sensor_mark_updated_with_time - mark the sensor is updated
++ * @sensor: pointer to sensor data struct
++ * @jif: jiffies value to update with
++ */
++static inline void
++peci_sensor_mark_updated_with_time(struct peci_sensor_data *sensor,
++ ulong jif)
++{
++ sensor->valid = 1;
++ sensor->last_updated = jif;
++}
++
++/**
++ * struct peci_sensor_conf - PECI sensor information
++ * @attribute: Sensor attribute
++ * @config: Part of channel parameters brought by single sensor
++ * @update_interval: time in jiffies needs to elapse to read sensor again
++ * @read: Read callback for data attributes. Mandatory if readable
++ * data attributes are present.
++ * Parameters are:
++ * @module_ctx: Pointer peci module context
++ * @sensor_conf: Pointer to sensor configuration object
++ * @sensor_data: Pointer to sensor data object
++ * @val: Pointer to returned value
++ * The function returns 0 on success or a negative error number.
++ * @write: Write callback for data attributes. Mandatory if writeable
++ * data attributes are present.
++ * Parameters are:
++ * @module_ctx: Pointer peci module context
++ * @sensor_conf: Pointer to sensor configuration object
++ * @sensor_data: Pointer to sensor data object
++ * @val: Value to write
++ * The function returns 0 on success or a negative error number.
++ */
++struct peci_sensor_conf {
++ const s32 attribute;
++ const u32 config;
++ const ulong update_interval;
++
++ int (*const read)(void *priv, struct peci_sensor_conf *sensor_conf,
++ struct peci_sensor_data *sensor_data,
++ s32 *val);
++ int (*const write)(void *priv, struct peci_sensor_conf *sensor_conf,
++ struct peci_sensor_data *sensor_data,
++ s32 val);
++};
++
++/**
++ * peci_sensor_get_config - get peci sensor configuration for provided channel
++ * @sensors: Sensors list
++ * @sensor_count: Sensors count
++ *
++ * Return: sensor configuration
++ */
++static inline u32 peci_sensor_get_config(struct peci_sensor_conf sensors[],
++ u8 sensor_count)
++{
++ u32 config = 0u;
++ int iter;
++
++ for (iter = 0; iter < sensor_count; ++iter)
++ config |= sensors[iter].config;
++
++ return config;
++}
++
++/**
++ * peci_sensor_get_ctx - get peci sensor context - both configuration and data
++ * @attribute: Sensor attribute
++ * @sensor_conf_list: Sensors configuration object list
++ * @sensor_conf: Sensor configuration object found
++ * @sensor_data_list: Sensors data object list, maybe NULL in case there is no
++ * need to find sensor data object
++ * @sensor_data: Sensor data object found, maybe NULL in case there is no need
++ * to find sensor data object
++ * @sensor_count: Sensor count
++ *
++ * Return: 0 on success or -EOPNOTSUPP in case sensor attribute not found
++ */
++static inline int peci_sensor_get_ctx(s32 attribute,
++ struct peci_sensor_conf
++ sensor_conf_list[],
++ struct peci_sensor_conf **sensor_conf,
++ struct peci_sensor_data
++ sensor_data_list[],
++ struct peci_sensor_data **sensor_data,
++ const u8 sensor_count)
++{
++ int iter;
++
++ for (iter = 0; iter < sensor_count; ++iter) {
++ if (attribute == sensor_conf_list[iter].attribute) {
++ *sensor_conf = &sensor_conf_list[iter];
++ if (sensor_data_list && sensor_data)
++ *sensor_data = &sensor_data_list[iter];
++ return 0;
++ }
++ }
++
++ return -EOPNOTSUPP;
++}
++
++/* Value for the most common parameter used for PCS accessing */
++#define PECI_PCS_PARAM_ZERO 0x0000u
++
++#define PECI_PCS_REGISTER_SIZE 4u /* PCS register size in bytes */
++
++/* PPL1 value to PPL2 value conversation macro */
++#define PECI_PCS_PPL1_TO_PPL2(ppl1_value) ((((u32)(ppl1_value)) * 12uL) / 10uL)
++
++#define PECI_PCS_PPL1_TIME_WINDOW 250 /* PPL1 Time Window value in ms */
++
++#define PECI_PCS_PPL2_TIME_WINDOW 10 /* PPL2 Time Window value in ms */
++
++/**
++ * union peci_pkg_power_sku_unit - PECI Package Power Unit PCS
++ * This register coresponds to the MSR@606h - MSR_RAPL_POWER_UNIT
++ * Accessing over PECI: PCS=0x1E, Parameter=0x0000
++ * @value: PCS register value
++ * @bits: PCS register bits
++ * @pwr_unit: Bits [3:0] - Power Unit
++ * @rsvd0: Bits [7:4]
++ * @eng_unit: Bits [12:8] - Energy Unit
++ * @rsvd1: Bits [15:13]
++ * @tim_unit: Bits [19:16] - Time Unit
++ * @rsvd2: Bits [31:20]
++ */
++union peci_pkg_power_sku_unit {
++ u32 value;
++ struct {
++ u32 pwr_unit : 4;
++ u32 rsvd0 : 4;
++ u32 eng_unit : 5;
++ u32 rsvd1 : 3;
++ u32 tim_unit : 4;
++ u32 rsvd2 : 12;
++ } __attribute__((__packed__)) bits;
++} __attribute__((__packed__));
++
++static_assert(sizeof(union peci_pkg_power_sku_unit) == PECI_PCS_REGISTER_SIZE);
++
++/**
++ * union peci_package_power_info_low - Platform and Package Power SKU (Low) PCS
++ * This PCS coresponds to the MSR@614h - PACKAGE_POWER_SKU, bits [31:0]
++ * Accessing over PECI: PCS=0x1C, parameter=0x00FF
++ * @value: PCS register value
++ * @bits: PCS register bits
++ * @pkg_tdp: Bits [14:0] - TDP Package Power
++ * @rsvd0: Bits [15:15]
++ * @pkg_min_pwr: Bits [30:16] - Minimal Package Power
++ * @rsvd1: Bits [31:31]
++ */
++union peci_package_power_info_low {
++ u32 value;
++ struct {
++ u32 pkg_tdp : 15;
++ u32 rsvd0 : 1;
++ u32 pkg_min_pwr : 15;
++ u32 rsvd1 : 1;
++ } __attribute__((__packed__)) bits;
++} __attribute__((__packed__));
++
++static_assert(sizeof(union peci_package_power_info_low) ==
++ PECI_PCS_REGISTER_SIZE);
++
++/**
++ * union peci_package_power_limit_high - Package Power Limit 2 PCS
++ * This PCS coresponds to the MSR@610h - PACKAGE_RAPL_LIMIT, bits [63:32]
++ * Accessing over PECI: PCS=0x1B, Parameter=0x0000
++ * @value: PCS register value
++ * @bits: PCS register bits
++ * @pwr_lim_2: Bits [14:0] - Power Limit 2
++ * @pwr_lim_2_en: Bits [15:15] - Power Limit 2 Enable
++ * @pwr_clmp_lim_2:Bits [16:16] - Package Clamping Limitation 2
++ * @pwr_lim_2_time:Bits [23:17] - Power Limit 2 Time Window
++ * @rsvd0: Bits [31:24]
++ */
++union peci_package_power_limit_high {
++ u32 value;
++ struct {
++ u32 pwr_lim_2 : 15;
++ u32 pwr_lim_2_en : 1;
++ u32 pwr_clmp_lim_2 : 1;
++ u32 pwr_lim_2_time : 7;
++ u32 rsvd0 : 8;
++ } __attribute__((__packed__)) bits;
++} __attribute__((__packed__));
++
++static_assert(sizeof(union peci_package_power_limit_high) ==
++ PECI_PCS_REGISTER_SIZE);
++
++/**
++ * union peci_package_power_limit_low - Package Power Limit 1 PCS
++ * This PCS coresponds to the MSR@610h - PACKAGE_RAPL_LIMIT, bits [31:0]
++ * Accessing over PECI: PCS=0x1A, Parameter=0x0000
++ * @value: PCS register value
++ * @bits: PCS register bits
++ * @pwr_lim_1: Bits [14:0] - Power Limit 1
++ * @pwr_lim_1_en: Bits [15:15] - Power Limit 1 Enable
++ * @pwr_clmp_lim_1:Bits [16:16] - Package Clamping Limitation 1
++ * @pwr_lim_1_time:Bits [23:17] - Power Limit 1 Time Window
++ * @rsvd0: Bits [31:24]
++ */
++union peci_package_power_limit_low {
++ u32 value;
++ struct {
++ u32 pwr_lim_1 : 15;
++ u32 pwr_lim_1_en : 1;
++ u32 pwr_clmp_lim_1 : 1;
++ u32 pwr_lim_1_time : 7;
++ u32 rsvd0 : 8;
++ } __attribute__((__packed__)) bits;
++} __attribute__((__packed__));
++
++static_assert(sizeof(union peci_package_power_limit_low) ==
++ PECI_PCS_REGISTER_SIZE);
++
++/**
++ * union peci_dram_power_info_high - DRAM Power Info high PCS
++ * This PCS coresponds to the MSR@61Ch - MSR_DRAM_POWER_INFO, bits [63:32]
++ * Accessing over PECI: PCS=0x23, Parameter=0x0000
++ * @value: PCS register value
++ * @bits: PCS register bits
++ * @max_pwr: Bits [14:0] - Maximal DRAM Power
++ * @rsvd0: Bits [15:15]
++ * @max_win: Bits [22:16] - Maximal Time Window
++ * @rsvd1: Bits [30:23]
++ * @lock: Bits [31:31] - Locking bit
++ */
++union peci_dram_power_info_high {
++ u32 value;
++ struct {
++ u32 max_pwr : 15;
++ u32 rsvd0 : 1;
++ u32 max_win : 7;
++ u32 rsvd1 : 8;
++ u32 lock : 1;
++ } __attribute__((__packed__)) bits;
++} __attribute__((__packed__));
++
++static_assert(sizeof(union peci_dram_power_info_high) ==
++ PECI_PCS_REGISTER_SIZE);
++
++/**
++ * union peci_dram_power_info_low - DRAM Power Info low PCS
++ * This PCS coresponds to the MSR@61Ch - MSR_DRAM_POWER_INFO, bits [31:0]
++ * Accessing over PECI: PCS=0x24, Parameter=0x0000
++ * @value: PCS register value
++ * @bits: PCS register bits
++ * @tdp: Bits [14:0] - Spec DRAM Power
++ * @rsvd0: Bits [15:15]
++ * @min_pwr: Bits [30:16] - Minimal DRAM Power
++ * @rsvd1: Bits [31:31]
++ */
++union peci_dram_power_info_low {
++ u32 value;
++ struct {
++ u32 tdp : 15;
++ u32 rsvd0 : 1;
++ u32 min_pwr : 15;
++ u32 rsvd1 : 1;
++ } __attribute__((__packed__)) bits;
++} __attribute__((__packed__));
++
++static_assert(sizeof(union peci_dram_power_info_low) == PECI_PCS_REGISTER_SIZE);
++
++/**
++ * union peci_dram_power_limit - DRAM Power Limit PCS
++ * This PCS coresponds to the MSR@618h - DRAM_PLANE_POWER_LIMIT, bits [31:0]
++ * Accessing over PECI: PCS=0x22, Parameter=0x0000
++ * @value: PCS register value
++ * @bits: PCS register bits
++ * @pp_pwr_lim: Bits [14:0] - Power Limit[0] for DDR domain,
++ * format: U11.3
++ * @pwr_lim_ctrl_en:Bits [15:15] - Power Limit[0] enable bit for
++ * DDR domain
++ * @rsvd0: Bits [16:16]
++ * @ctrl_time_win: Bits [23:17] - Power Limit[0] time window for
++ * DDR domain
++ * @rsvd1: Bits [31:24]
++ */
++union peci_dram_power_limit {
++ u32 value;
++ struct {
++ u32 pp_pwr_lim : 15;
++ u32 pwr_lim_ctrl_en : 1;
++ u32 rsvd0 : 1;
++ u32 ctrl_time_win : 7;
++ u32 rsvd1 : 8;
++ } __attribute__((__packed__)) bits;
++} __attribute__((__packed__));
++
++static_assert(sizeof(union peci_dram_power_limit) == PECI_PCS_REGISTER_SIZE);
++
++/**
++ * peci_pcs_xn_to_munits - function converting value in units in x.N format to
++ * milli units (millijoules, milliseconds, millidegrees) in regular format
++ * @x_n_value: Value in units in x.n format
++ * @n: n factor for x.n format
++
++ *
++ * Return: value in milli units (millijoules, milliseconds, millidegrees)
++ * in regular format
++ */
++static inline u64 peci_pcs_xn_to_munits(u32 x_n_value, u8 n)
++{
++ /* Convert value in units in x.n format to milli units in x.n format */
++ u64 mx_n_value = (u64)x_n_value * 1000uLL;
++ /* Convert x.n format to regular format */
++ return mx_n_value >> n;
++}
++
++/**
++ * peci_pcs_munits_to_xn - function converting value in milli units
++ * (millijoules,milliseconds, millidegrees) in regular format to value in units
++ * in x.n format
++ * @mu_value: Value in milli units (millijoules, milliseconds, millidegrees)
++ * @n: n factor for x.n format, assumed here maximal value for n is 32
++ *
++ * Return: value in units in x.n format
++ */
++static inline u32 peci_pcs_munits_to_xn(u32 mu_value, u8 n)
++{
++ /* Convert value in milli units (regular format) to the x.n format */
++ u64 mx_n_value = (u64)mu_value << n;
++ /* Convert milli units (x.n format) to units (x.n format) */
++ if (mx_n_value > (u64)U32_MAX) {
++ do_div(mx_n_value, 1000uL);
++ return (u32)mx_n_value;
++ } else {
++ return (u32)mx_n_value / 1000uL;
++ }
++}
++
++/**
++ * peci_pcs_read - read PCS register
++ * @peci_mgr: PECI client manager handle
++ * @index: PCS index
++ * @parameter: PCS parameter
++ * @reg: Pointer to the variable read value is going to be put
++ *
++ * Return: 0 if succeeded,
++ * -EINVAL if there are null pointers among arguments,
++ * other values in case other errors.
++ */
++static inline int peci_pcs_read(struct peci_client_manager *peci_mgr, u8 index,
++ u16 parameter, u32 *reg)
++{
++ u32 pcs_reg;
++ int ret;
++
++ if (!reg)
++ return -EINVAL;
++
++ ret = peci_client_read_package_config(peci_mgr, index, parameter,
++ (u8 *)&pcs_reg);
++ if (!ret)
++ *reg = le32_to_cpup((__le32 *)&pcs_reg);
++
++ return ret;
++}
++
++/**
++ * peci_pcs_write - write PCS register
++ * @peci_mgr: PECI client manager handle
++ * @index: PCS index
++ * @parameter: PCS parameter
++ * @reg: Variable which value is going to be written to the PCS
++ *
++ * Return: 0 if succeeded, other values in case an error.
++ */
++static inline int peci_pcs_write(struct peci_client_manager *peci_mgr, u8 index,
++ u16 parameter, u32 reg)
++{
++ u32 pcs_reg;
++ int ret;
++
++ pcs_reg = cpu_to_le32p(&reg);
++
++ ret = peci_client_write_package_config(peci_mgr, index, parameter,
++ (u8 *)&pcs_reg);
++
++ return ret;
++}
++
++/**
++ * peci_pcs_calc_pwr_from_eng - calculate power (in milliwatts) based on
++ * energy reading
++ * @dev: Device handle
++ * @energy: Energy reading context
++ * @energy_cnt: Raw energy reading
++ * @unit: Calculation factor
++ * @power_val_in_mW: Pointer to the variable calculation result is going to
++ * be put
++ *
++ * Return: 0 if succeeded,
++ * -EINVAL if there are null pointers among arguments,
++ * -EAGAIN if calculation is skipped.
++ */
++static inline int peci_pcs_calc_pwr_from_eng(struct device *dev,
++ struct peci_sensor_data *sensor,
++ u32 energy_cnt, u32 unit,
++ s32 *power_in_mW)
++{
++ ulong jif = jiffies;
++ ulong elapsed;
++ int ret;
++
++ if (!dev || !sensor || !power_in_mW)
++ return -EINVAL;
++
++ elapsed = jif - sensor->last_updated;
++
++ dev_dbg(dev, "raw energy before %u, raw energy now %u, unit %u, jiffies elapsed %lu\n",
++ sensor->value, energy_cnt, unit, elapsed);
++
++ /*
++ * Don't calculate average power for first counter read last counter
++ * read was more than 60 minutes ago (jiffies did not wrap and power
++ * calculation does not overflow or underflow).
++ */
++ if (sensor->last_updated > 0 && elapsed < (HZ * 3600)) {
++ u32 energy_consumed;
++ u64 energy_consumed_in_mJ;
++ u64 energy_by_jiffies;
++
++ /* Take care here about energy counter rollover */
++ if (energy_cnt >= (u32)(sensor->value))
++ energy_consumed = energy_cnt - (u32)(sensor->value);
++ else
++ energy_consumed = (U32_MAX - (u32)(sensor->value)) +
++ energy_cnt + 1u;
++
++ /* Calculate the energy here */
++ energy_consumed_in_mJ =
++ peci_pcs_xn_to_munits(energy_consumed, unit);
++ energy_by_jiffies = energy_consumed_in_mJ * HZ;
++
++ /* Calculate the power */
++ if (energy_by_jiffies > (u64)U32_MAX) {
++ do_div(energy_by_jiffies, elapsed);
++ *power_in_mW = (long)energy_by_jiffies;
++ } else {
++ *power_in_mW = (u32)energy_by_jiffies / elapsed;
++ }
++
++ dev_dbg(dev, "raw energy consumed %u, scaled energy consumed %llumJ, scaled power %dmW\n",
++ energy_consumed, energy_consumed_in_mJ, *power_in_mW);
++
++ ret = 0;
++ } else {
++ dev_dbg(dev, "skipping calculate power, try again\n");
++ *power_in_mW = 0;
++ ret = -EAGAIN;
++ }
++
++ /* Update sensor context */
++ sensor->value = energy_cnt;
++
++ return ret;
++}
++
++/**
++ * peci_pcs_get_units - read units (power, energy, time) from HW or cache
++ * @peci_mgr: PECI client manager handle
++ * @units: Pointer to the variable read value is going to be put in case reading
++ * from HW
++ * @valid: Flag telling cache is valid
++ *
++ * Return: 0 if succeeded
++ * -EINVAL if there are null pointers among arguments,
++ * other values in case other errors.
++ */
++static inline int peci_pcs_get_units(struct peci_client_manager *peci_mgr,
++ union peci_pkg_power_sku_unit *units,
++ bool *valid)
++{
++ int ret = 0;
++
++ if (!valid)
++ return -EINVAL;
++
++ if (!(*valid)) {
++ ret = peci_pcs_read(peci_mgr, PECI_MBX_INDEX_TDP_UNITS,
++ PECI_PCS_PARAM_ZERO, &units->value);
++ if (!ret)
++ *valid = true;
++ }
++ return ret;
++}
++
++/**
++ * peci_pcs_calc_plxy_time_window - calculate power limit time window in
++ * PCS format. To figure that value out needs to solve the following equation:
++ * time_window = (1+(x/4)) * (2 ^ y), where time_window is known value and
++ * x and y values are variables to find.
++ * Return value is about X & Y compostion according to the following:
++ * x = ret[6:5], y = ret[4:0].
++ * @pl_tim_wnd_in_xn: PPL time window in X-n format
++ *
++ * Return: Power limit time window value
++ */
++static inline u32 peci_pcs_calc_plxy_time_window(u32 pl_tim_wnd_in_xn)
++{
++ u32 x = 0u;
++ u32 y = 0u;
++
++ /* Calculate y first */
++ while (pl_tim_wnd_in_xn > 7u) {
++ pl_tim_wnd_in_xn >>= 1;
++ y++;
++ }
++
++ /* Correct y value */
++ if (pl_tim_wnd_in_xn >= 4u)
++ y += 2u;
++ else if (pl_tim_wnd_in_xn >= 2u)
++ y += 1u;
++
++ /* Calculate x then */
++ if (pl_tim_wnd_in_xn >= 4u)
++ x = pl_tim_wnd_in_xn % 4;
++ else
++ x = 0u;
++
++ return ((x & 0x3) << 5) | (y & 0x1F);
++}
++
+ #endif /* __PECI_HWMON_H */
+diff --git a/include/linux/mfd/intel-peci-client.h b/include/linux/mfd/intel-peci-client.h
+index dbf0670..ba9c03d 100644
+--- a/include/linux/mfd/intel-peci-client.h
++++ b/include/linux/mfd/intel-peci-client.h
+@@ -1,5 +1,5 @@
+ /* SPDX-License-Identifier: GPL-2.0 */
+-/* Copyright (c) 2018-2019 Intel Corporation */
++/* Copyright (c) 2018-2020 Intel Corporation */
+
+ #ifndef __LINUX_MFD_INTEL_PECI_CLIENT_H
+ #define __LINUX_MFD_INTEL_PECI_CLIENT_H
+@@ -131,4 +131,36 @@ peci_client_read_package_config(struct peci_client_manager *priv,
+ return 0;
+ }
+
++/**
++ * peci_client_write_package_config - write to the Package Configuration Space
++ * @priv: driver private data structure
++ * @index: encoding index for the requested service
++ * @param: parameter to specify the exact data being requested
++ * @data: data buffer with values to write
++ * Context: can sleep
++ *
++ * Return: zero on success, else a negative error code.
++ */
++static inline int
++peci_client_write_package_config(struct peci_client_manager *priv,
++ u8 index, u16 param, u8 *data)
++{
++ struct peci_rd_pkg_cfg_msg msg;
++ int ret;
++
++ msg.addr = priv->client->addr;
++ msg.index = index;
++ msg.param = param;
++ msg.rx_len = 4u;
++ memcpy(msg.pkg_config, data, msg.rx_len);
++
++ ret = peci_command(priv->client->adapter, PECI_CMD_WR_PKG_CFG, &msg);
++ if (!ret) {
++ if (msg.cc != PECI_DEV_CC_SUCCESS)
++ ret = -EAGAIN;
++ }
++
++ return ret;
++}
++
+ #endif /* __LINUX_MFD_INTEL_PECI_CLIENT_H */
+diff --git a/include/uapi/linux/peci-ioctl.h b/include/uapi/linux/peci-ioctl.h
+index c0f0bb3..1c76c7f 100644
+--- a/include/uapi/linux/peci-ioctl.h
++++ b/include/uapi/linux/peci-ioctl.h
+@@ -226,12 +226,15 @@ struct peci_rd_pkg_cfg_msg {
+ __u16 param;
+ /* When index is PECI_MBX_INDEX_CPU_ID */
+ #define PECI_PKG_ID_CPU_ID 0x0000 /* CPUID Info */
++#define PECI_PKG_POWER_SKU_UNIT 0x0000 /* Time, Energy, Power units */
+ #define PECI_PKG_ID_PLATFORM_ID 0x0001 /* Platform ID */
+ #define PECI_PKG_ID_UNCORE_ID 0x0002 /* Uncore Device ID */
+ #define PECI_PKG_ID_MAX_THREAD_ID 0x0003 /* Max Thread ID */
+ #define PECI_PKG_ID_MICROCODE_REV 0x0004 /* CPU Microcode Update Revision */
+ #define PECI_PKG_ID_MACHINE_CHECK_STATUS 0x0005 /* Machine Check Status */
+-#define PECI_PKG_ID_PKG_ENERGY_STATUS 0x00ff /* Average Energy */
++#define PECI_PKG_ID_CPU_PACKAGE 0x00ff /* CPU package ID*/
++#define PECI_PKG_ID_DIMM 0x00ff /* DIMM ID*/
++#define PECI_PKG_ID_PLATFORM 0x00fe /* Entire platform ID */
+
+ __u8 rx_len;
+ __u8 cc;
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0114-hwmon-peci-cpupower-extension.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0114-hwmon-peci-cpupower-extension.patch
new file mode 100644
index 000000000..72457917c
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0114-hwmon-peci-cpupower-extension.patch
@@ -0,0 +1,708 @@
+From ca6f311baec11435dbd27b45c83eba0bfcb2ebdc Mon Sep 17 00:00:00 2001
+From: Zbigniew Lukwinski <zbigniew.lukwinski@linux.intel.com>
+Date: Wed, 17 Jun 2020 07:11:07 +0200
+Subject: [PATCH] hwmon: peci: cpupower extension
+
+1. Use hwmon peci pcs utils to refactor peci cpupower module.
+2. Enable CPU power limit, power limit max (TDP) setting,
+ power limit min setting reading and expose them under
+ power1_cap, power1_cap_max, power1_cap_min.
+3. Enable CPU power limit writing through power1_cap.
+
+Tested:
+ * on WilsonCity platform,
+ * power1_avarage works as before the change,
+ * power1_cap, power1_cap_max, power1_cap_min work as expected.
+
+Signed-off-by: Zbigniew Lukwinski <zbigniew.lukwinski@linux.intel.com>
+---
+ Documentation/hwmon/peci-cpupower.rst | 13 +-
+ drivers/hwmon/Kconfig | 4 +-
+ drivers/hwmon/peci-cpupower.c | 550 +++++++++++++++++++++++++++-------
+ 3 files changed, 446 insertions(+), 121 deletions(-)
+
+diff --git a/Documentation/hwmon/peci-cpupower.rst b/Documentation/hwmon/peci-cpupower.rst
+index 4d7bd61..1e1f4e0 100644
+--- a/Documentation/hwmon/peci-cpupower.rst
++++ b/Documentation/hwmon/peci-cpupower.rst
+@@ -38,15 +38,22 @@ Description
+ -----------
+
+ This driver implements a generic PECI hwmon feature which provides
+-average power consumption readings of the CPU package based on energy counter
+-accessible using the PECI Client Command Suite via the processor PECI client.
++average power consumption readings of the CPU package based on energy counter.
+
+ Power values are average power since last measure given in milli Watt and
+ will be measurable only when the target CPU is powered on.
+
++Driver provides current package power limit, maximal (TDP) and minimal power
++setting as well.
++All needed processor registers are accessible using the PECI Client Command
++Suite via the processor PECI client.
++
+ ``sysfs`` interface
+ -------------------
+ ======================= =======================================================
++power1_label Provides string "cpu power".
+ power1_average Provides average power since last read in milli Watt.
+-power1_label Provides string "Average Power".
++power1_cap Provides current package power limit 1 (PPL1).
++power1_cap_max Provides maximal (TDP) package power setting.
++power1_cap_min Provides minimal package power setting.
+ ======================= =======================================================
+diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
+index 07d8826..807b489 100644
+--- a/drivers/hwmon/Kconfig
++++ b/drivers/hwmon/Kconfig
+@@ -1367,8 +1367,8 @@ config SENSORS_PECI_CPUPOWER
+ select MFD_INTEL_PECI_CLIENT
+ help
+ If you say yes here you get support for the generic Intel PECI
+- cputemp driver which provides average engergy
+- readings of the CPU package using
++ cpupower driver which provides average engergy readings of the CPU package,
++ current package power limit, maximal (TDP) and minimal power setting using
+ the PECI Client Command Suite via the processor PECI client.
+ Check Documentation/hwmon/peci-cpupower for details.
+
+diff --git a/drivers/hwmon/peci-cpupower.c b/drivers/hwmon/peci-cpupower.c
+index a3a8fc1..d0a3af7 100644
+--- a/drivers/hwmon/peci-cpupower.c
++++ b/drivers/hwmon/peci-cpupower.c
+@@ -9,159 +9,478 @@
+ #include <linux/platform_device.h>
+ #include "peci-hwmon.h"
+
+-#define POWER_DEFAULT_CHANNEL_NUMS 1
++#define PECI_CPUPOWER_CHANNEL_COUNT 1 /* Supported channels number */
++
++#define PECI_CPUPOWER_SENSOR_COUNT 4 /* Supported sensors/readings number */
+
+ struct peci_cpupower {
+- struct peci_client_manager *mgr;
+ struct device *dev;
++ struct peci_client_manager *mgr;
+ char name[PECI_NAME_SIZE];
+- const struct cpu_gen_info *gen_info;
+- struct peci_sensor_data energy;
+- long avg_power_val;
+- u64 core_mask;
+- u32 power_config[POWER_DEFAULT_CHANNEL_NUMS + 1];
+- uint config_idx;
++ u32 power_config[PECI_CPUPOWER_CHANNEL_COUNT + 1];
++ u32 config_idx;
+ struct hwmon_channel_info power_info;
+ const struct hwmon_channel_info *info[2];
+ struct hwmon_chip_info chip;
+-};
+
+-enum cpupower_channels {
+- average_power,
+-};
++ struct peci_sensor_data
++ sensor_data_list[PECI_CPUPOWER_CHANNEL_COUNT]
++ [PECI_CPUPOWER_SENSOR_COUNT];
++
++ s32 avg_power_val;
++ union peci_pkg_power_sku_unit units;
++ bool units_valid;
+
+-static const u32 config_table[POWER_DEFAULT_CHANNEL_NUMS] = {
+- /* average power */
+- HWMON_P_LABEL | HWMON_P_AVERAGE,
++ u32 ppl1_time_window;
++ u32 ppl2_time_window;
++ bool ppl_time_windows_valid;
+ };
+
+-static const char *cpupower_label[POWER_DEFAULT_CHANNEL_NUMS] = {
+- "Average Power",
++static const char *peci_cpupower_labels[PECI_CPUPOWER_CHANNEL_COUNT] = {
++ "cpu power",
+ };
+
+-static int get_average_power(struct peci_cpupower *priv)
++/**
++ * peci_cpupower_read_cpu_pkg_pwr_info_low - read PCS Platform Power SKU low.
++ * @peci_mgr: PECI client manager handle
++ * @reg: Pointer to the variable read value is going to be put
++ *
++ * Return: 0 if succeeded, other values in case an error.
++ */
++static inline int
++peci_cpupower_read_cpu_pkg_pwr_info_low(struct peci_client_manager *peci_mgr,
++ union peci_package_power_info_low *reg)
+ {
+- u8 pkg_cfg[4];
++ return peci_pcs_read(peci_mgr, PECI_MBX_INDEX_TDP,
++ PECI_PKG_ID_CPU_PACKAGE, &reg->value);
++}
++
++/**
++ * peci_cpupower_read_cpu_pkg_pwr_lim_low - read PCS Package Power Limit Low
++ * @peci_mgr: PECI client manager handle
++ * @reg: Pointer to the variable read value is going to be put
++ *
++ * Return: 0 if succeeded, other values in case an error.
++ */
++static inline int
++peci_cpupower_read_cpu_pkg_pwr_lim_low(struct peci_client_manager *peci_mgr,
++ union peci_package_power_limit_low *reg)
++{
++ return peci_pcs_read(peci_mgr, PECI_MBX_INDEX_PKG_POWER_LIMIT1,
++ PECI_PCS_PARAM_ZERO, &reg->value);
++}
++
++static int
++peci_cpupower_get_average_power(void *ctx, struct peci_sensor_conf *sensor_conf,
++ struct peci_sensor_data *sensor_data,
++ s32 *val)
++{
++ struct peci_cpupower *priv = (struct peci_cpupower *)ctx;
++ u32 energy_cnt;
++ ulong jif;
+ int ret;
+
+- if (!peci_sensor_need_update(&priv->energy))
++ if (!peci_sensor_need_update_with_time(sensor_data,
++ sensor_conf->update_interval)) {
++ *val = priv->avg_power_val;
++ dev_dbg(priv->dev,
++ "skip reading peci, average power %dmW\n", *val);
+ return 0;
++ }
+
+- ret = peci_client_read_package_config(priv->mgr,
+- PECI_MBX_INDEX_TDP_UNITS,
+- PECI_PKG_ID_CPU_PACKAGE,
+- pkg_cfg);
++ ret = peci_pcs_get_units(priv->mgr, &priv->units, &priv->units_valid);
++ if (ret) {
++ dev_dbg(priv->dev, "not able to read units\n");
++ return ret;
++ }
+
+- u32 power_unit = ((le32_to_cpup((__le32 *)pkg_cfg)) & 0x1f00) >> 8;
++ jif = jiffies;
++ ret = peci_pcs_read(priv->mgr, PECI_MBX_INDEX_ENERGY_COUNTER,
++ PECI_PKG_ID_CPU_PACKAGE, &energy_cnt);
+
+- dev_dbg(priv->dev, "cpupower units %d (1J/pow(2, unit))\n",
+- power_unit);
++ if (ret) {
++ dev_dbg(priv->dev, "not able to read package energy\n");
++ return ret;
++ }
+
+- ret = peci_client_read_package_config(priv->mgr,
+- PECI_MBX_INDEX_ENERGY_COUNTER,
+- PECI_PKG_ID_CPU_PACKAGE,
+- pkg_cfg);
+- if (!ret) {
+- u32 energy_cnt = le32_to_cpup((__le32 *)pkg_cfg);
+- ulong jif = jiffies;
+- ulong elapsed = (jif - priv->energy.last_updated);
+- long power_val = 0;
+- /*
+- * Don't calculate average power for first counter read or
+- * counter wrapped around or last counter read was more than
+- * 60 minutes ago (jiffies did not wrap and power calculation
+- * does not overflow or underflow
+- */
+- if (priv->energy.last_updated > 0 &&
+- energy_cnt > priv->energy.value &&
+- (elapsed < (HZ * 3600))) {
+- power_val = (long)(energy_cnt - priv->energy.value)
+- / elapsed * HZ;
+- dev_dbg(priv->dev, "countDiff %d, jiffes elapsed %d, raw powerValue %d scale to %d mW\n",
+- (long)(energy_cnt - priv->energy.value),
+- elapsed, power_val,
+- power_val >> (power_unit - 10));
+- } else {
+- dev_dbg(priv->dev, "countDiff %d, jiffes elapsed %d, skipping calculate power, try agin\n",
+- (long)(energy_cnt - priv->energy.value),
+- elapsed);
+- ret = -EAGAIN;
+- }
+-
+- priv->energy.value = energy_cnt;
+- priv->avg_power_val = power_val >> ((power_unit - 10));
+- peci_sensor_mark_updated(&priv->energy);
+-
+- dev_dbg(priv->dev, "energy counter 0x%8x, average power %dmW, jif %u, HZ is %d jiffies\n",
+- priv->energy.value, priv->avg_power_val,
+- jif, HZ);
++ ret = peci_pcs_calc_pwr_from_eng(priv->dev, sensor_data, energy_cnt,
++ priv->units.bits.eng_unit, val);
++
++ priv->avg_power_val = *val;
++ peci_sensor_mark_updated_with_time(sensor_data, jif);
++
++ dev_dbg(priv->dev, "average power %dmW, jif %lu, HZ is %d jiffies\n",
++ *val, jif, HZ);
++
++ return ret;
++}
++
++static int
++peci_cpupower_get_power_limit(void *ctx, struct peci_sensor_conf *sensor_conf,
++ struct peci_sensor_data *sensor_data,
++ s32 *val)
++{
++ struct peci_cpupower *priv = (struct peci_cpupower *)ctx;
++ union peci_package_power_limit_low power_limit;
++ ulong jif;
++ int ret;
++
++ if (!peci_sensor_need_update_with_time(sensor_data,
++ sensor_conf->update_interval)) {
++ *val = sensor_data->value;
++ dev_dbg(priv->dev, "skip reading peci, power limit %dmW\n",
++ *val);
++ return 0;
++ }
++
++ ret = peci_pcs_get_units(priv->mgr, &priv->units, &priv->units_valid);
++ if (ret) {
++ dev_dbg(priv->dev, "not able to read units\n");
++ return ret;
++ }
++
++ jif = jiffies;
++ ret = peci_cpupower_read_cpu_pkg_pwr_lim_low(priv->mgr, &power_limit);
++ if (ret) {
++ dev_dbg(priv->dev, "not able to read power limit\n");
++ return ret;
+ }
++
++ *val = peci_pcs_xn_to_munits(power_limit.bits.pwr_lim_1,
++ priv->units.bits.pwr_unit);
++
++ sensor_data->value = *val;
++ peci_sensor_mark_updated_with_time(sensor_data, jif);
++
++ dev_dbg(priv->dev, "raw power limit %u, unit %u, power limit %d\n",
++ power_limit.bits.pwr_lim_1, priv->units.bits.pwr_unit, *val);
++
+ return ret;
+ }
+
+-static int cpupower_read_string(struct device *dev,
+- enum hwmon_sensor_types type,
+- u32 attr, int channel, const char **str)
++static int
++peci_cpupower_set_power_limit(void *ctx, struct peci_sensor_conf *sensor_conf,
++ struct peci_sensor_data *sensor_data,
++ s32 val)
+ {
+- if (attr != hwmon_power_label)
+- return -EOPNOTSUPP;
+- if (channel >= POWER_DEFAULT_CHANNEL_NUMS)
++ struct peci_cpupower *priv = (struct peci_cpupower *)ctx;
++ union peci_package_power_limit_high power_limit_high;
++ union peci_package_power_limit_low power_limit_low;
++ int ret;
++
++ ret = peci_pcs_get_units(priv->mgr, &priv->units, &priv->units_valid);
++ if (ret) {
++ dev_dbg(priv->dev, "not able to read units\n");
++ return ret;
++ }
++
++ ret = peci_cpupower_read_cpu_pkg_pwr_lim_low(priv->mgr,
++ &power_limit_low);
++ if (ret) {
++ dev_dbg(priv->dev, "not able to read package power limit 1\n");
++ return ret;
++ }
++
++ ret = peci_pcs_read(priv->mgr, PECI_MBX_INDEX_PKG_POWER_LIMIT2,
++ PECI_PCS_PARAM_ZERO, &power_limit_high.value);
++ if (ret) {
++ dev_dbg(priv->dev, "not able to read package power limit 2\n");
++ return ret;
++ }
++
++ /* Calculate PPL time windows if needed */
++ if (!priv->ppl_time_windows_valid) {
++ priv->ppl1_time_window =
++ peci_pcs_calc_plxy_time_window(peci_pcs_munits_to_xn(
++ PECI_PCS_PPL1_TIME_WINDOW,
++ priv->units.bits.tim_unit));
++ priv->ppl2_time_window =
++ peci_pcs_calc_plxy_time_window(peci_pcs_munits_to_xn(
++ PECI_PCS_PPL2_TIME_WINDOW,
++ priv->units.bits.tim_unit));
++ priv->ppl_time_windows_valid = true;
++ }
++
++ /* Enable or disable power limitation */
++ if (val > 0) {
++ /* Set PPL1 */
++ power_limit_low.bits.pwr_lim_1 =
++ peci_pcs_munits_to_xn(val, priv->units.bits.pwr_unit);
++ power_limit_low.bits.pwr_lim_1_en = 1u;
++ power_limit_low.bits.pwr_clmp_lim_1 = 1u;
++ power_limit_low.bits.pwr_lim_1_time = priv->ppl1_time_window;
++
++ /* Set PPL2 */
++ power_limit_high.bits.pwr_lim_2 =
++ peci_pcs_munits_to_xn(PECI_PCS_PPL1_TO_PPL2(val),
++ priv->units.bits.pwr_unit);
++ power_limit_high.bits.pwr_lim_2_en = 1u;
++ power_limit_high.bits.pwr_clmp_lim_2 = 1u;
++ power_limit_high.bits.pwr_lim_2_time = priv->ppl2_time_window;
++ } else {
++ power_limit_low.bits.pwr_lim_1 = 0u;
++ power_limit_low.bits.pwr_lim_1_en = 0u;
++ power_limit_low.bits.pwr_clmp_lim_1 = 0u;
++ power_limit_high.bits.pwr_lim_2 = 0u;
++ power_limit_high.bits.pwr_lim_2_en = 0u;
++ power_limit_high.bits.pwr_clmp_lim_2 = 0u;
++ }
++
++ ret = peci_pcs_write(priv->mgr, PECI_MBX_INDEX_PKG_POWER_LIMIT1,
++ PECI_PCS_PARAM_ZERO, power_limit_low.value);
++ if (ret) {
++ dev_dbg(priv->dev, "not able to write package power limit 1\n");
++ return ret;
++ }
++
++ ret = peci_pcs_write(priv->mgr, PECI_MBX_INDEX_PKG_POWER_LIMIT2,
++ PECI_PCS_PARAM_ZERO, power_limit_high.value);
++ if (ret) {
++ dev_dbg(priv->dev, "not able to write package power limit 2\n");
++ return ret;
++ }
++
++ dev_dbg(priv->dev,
++ "power limit %d, unit %u, raw package power limit 1 %u,\n",
++ val, priv->units.bits.pwr_unit, power_limit_low.bits.pwr_lim_1);
++
++ return ret;
++}
++
++static int
++peci_cpupower_read_max_power(void *ctx, struct peci_sensor_conf *sensor_conf,
++ struct peci_sensor_data *sensor_data,
++ s32 *val)
++{
++ struct peci_cpupower *priv = (struct peci_cpupower *)ctx;
++ union peci_package_power_info_low power_info;
++ ulong jif;
++ int ret;
++
++ if (!peci_sensor_need_update_with_time(sensor_data,
++ sensor_conf->update_interval)) {
++ *val = sensor_data->value;
++ dev_dbg(priv->dev, "skip reading peci, max power %dmW\n", *val);
++ return 0;
++ }
++
++ ret = peci_pcs_get_units(priv->mgr, &priv->units, &priv->units_valid);
++ if (ret) {
++ dev_dbg(priv->dev, "not able to read units\n");
++ return ret;
++ }
++
++ jif = jiffies;
++ ret = peci_cpupower_read_cpu_pkg_pwr_info_low(priv->mgr, &power_info);
++ if (ret) {
++ dev_dbg(priv->dev, "not able to read package power info\n");
++ return ret;
++ }
++
++ *val = peci_pcs_xn_to_munits(power_info.bits.pkg_tdp,
++ priv->units.bits.pwr_unit);
++
++ sensor_data->value = *val;
++ peci_sensor_mark_updated_with_time(sensor_data, jif);
++
++ dev_dbg(priv->dev, "raw max power %u, unit %u, max power %dmW\n",
++ power_info.bits.pkg_tdp, priv->units.bits.pwr_unit, *val);
++
++ return ret;
++}
++
++static int
++peci_cpupower_read_min_power(void *ctx, struct peci_sensor_conf *sensor_conf,
++ struct peci_sensor_data *sensor_data,
++ s32 *val)
++{
++ struct peci_cpupower *priv = (struct peci_cpupower *)ctx;
++ union peci_package_power_info_low power_info;
++ ulong jif;
++ int ret;
++
++ if (!peci_sensor_need_update_with_time(sensor_data,
++ sensor_conf->update_interval)) {
++ *val = sensor_data->value;
++ dev_dbg(priv->dev, "skip reading peci, min power %dmW\n",
++ *val);
++ return 0;
++ }
++
++ ret = peci_pcs_get_units(priv->mgr, &priv->units, &priv->units_valid);
++ if (ret) {
++ dev_dbg(priv->dev, "not able to read units\n");
++ return ret;
++ }
++
++ jif = jiffies;
++ ret = peci_cpupower_read_cpu_pkg_pwr_info_low(priv->mgr, &power_info);
++ if (ret) {
++ dev_dbg(priv->dev, "not able to read package power info\n");
++ return ret;
++ }
++
++ *val = peci_pcs_xn_to_munits(power_info.bits.pkg_min_pwr,
++ priv->units.bits.pwr_unit);
++
++ sensor_data->value = *val;
++ peci_sensor_mark_updated_with_time(sensor_data, jif);
++
++ dev_dbg(priv->dev, "raw min power %u, unit %u, min power %dmW\n",
++ power_info.bits.pkg_min_pwr, priv->units.bits.pwr_unit, *val);
++
++ return ret;
++}
++
++static struct peci_sensor_conf
++peci_cpupower_cfg[PECI_CPUPOWER_CHANNEL_COUNT][PECI_CPUPOWER_SENSOR_COUNT] = {
++ /* Channel 0 - Power */
++ {
++ {
++ .attribute = hwmon_power_average,
++ .config = HWMON_P_AVERAGE,
++ .update_interval = UPDATE_INTERVAL_100MS,
++ .read = peci_cpupower_get_average_power,
++ .write = NULL,
++ },
++ {
++ .attribute = hwmon_power_cap,
++ .config = HWMON_P_CAP,
++ .update_interval = UPDATE_INTERVAL_100MS,
++ .read = peci_cpupower_get_power_limit,
++ .write = peci_cpupower_set_power_limit,
++ },
++ {
++ .attribute = hwmon_power_cap_max,
++ .config = HWMON_P_CAP_MAX,
++ .update_interval = UPDATE_INTERVAL_10S,
++ .read = peci_cpupower_read_max_power,
++ .write = NULL,
++ },
++ {
++ .attribute = hwmon_power_cap_min,
++ .config = HWMON_P_CAP_MIN,
++ .update_interval = UPDATE_INTERVAL_10S,
++ .read = peci_cpupower_read_min_power,
++ .write = NULL,
++ },
++ },
++};
++
++static int
++peci_cpupower_read_string(struct device *dev, enum hwmon_sensor_types type,
++ u32 attr, int channel, const char **str)
++{
++ if (attr != hwmon_power_label || channel >= PECI_CPUPOWER_CHANNEL_COUNT)
+ return -EOPNOTSUPP;
+- *str = cpupower_label[channel];
++
++ if (str)
++ *str = peci_cpupower_labels[channel];
++ else
++ return -EINVAL;
+
+ return 0;
+ }
+
+-static int cpupower_read(struct device *dev,
+- enum hwmon_sensor_types type,
+- u32 attr, int channel, long *val)
++static int
++peci_cpupower_read(struct device *dev, enum hwmon_sensor_types type,
++ u32 attr, int channel, long *val)
+ {
+ struct peci_cpupower *priv = dev_get_drvdata(dev);
++ struct peci_sensor_conf *sensor_conf;
++ struct peci_sensor_data *sensor_data;
+ int ret;
+
+- if (channel >= POWER_DEFAULT_CHANNEL_NUMS ||
+- !(priv->power_config[channel] & BIT(attr)))
++ if (!priv || !val)
++ return -EINVAL;
++
++ if (channel >= PECI_CPUPOWER_CHANNEL_COUNT)
+ return -EOPNOTSUPP;
+
+- switch (attr) {
+- case hwmon_power_average:
+- switch (channel) {
+- case average_power:
+- ret = get_average_power(priv);
+- if (ret)
+- break;
+-
+- *val = priv->avg_power_val;
+- break;
+- default:
+- break;
+- }
+- break;
+- default:
++ ret = peci_sensor_get_ctx(attr, peci_cpupower_cfg[channel],
++ &sensor_conf, priv->sensor_data_list[channel],
++ &sensor_data,
++ ARRAY_SIZE(peci_cpupower_cfg[channel]));
++ if (ret)
++ return ret;
++
++ if (sensor_conf->read) {
++ s32 tmp;
++
++ ret = sensor_conf->read(priv, sensor_conf, sensor_data, &tmp);
++ if (!ret)
++ *val = (long)tmp;
++ } else {
+ ret = -EOPNOTSUPP;
+- break;
+ }
+
+ return ret;
+ }
+
+-static umode_t cpupower_is_visible(const void *data,
+- enum hwmon_sensor_types type,
+- u32 attr, int channel)
++static int
++peci_cpupower_write(struct device *dev, enum hwmon_sensor_types type,
++ u32 attr, int channel, long val)
+ {
+- const struct peci_cpupower *priv = data;
++ struct peci_cpupower *priv = dev_get_drvdata(dev);
++ struct peci_sensor_conf *sensor_conf;
++ struct peci_sensor_data *sensor_data;
++ int ret;
++
++ if (!priv)
++ return -EINVAL;
+
+- if (channel < POWER_DEFAULT_CHANNEL_NUMS ||
+- (priv->power_config[channel] & BIT(attr)))
++ if (channel >= PECI_CPUPOWER_CHANNEL_COUNT)
++ return -EOPNOTSUPP;
++
++ ret = peci_sensor_get_ctx(attr, peci_cpupower_cfg[channel],
++ &sensor_conf, priv->sensor_data_list[channel],
++ &sensor_data,
++ ARRAY_SIZE(peci_cpupower_cfg[channel]));
++ if (ret)
++ return ret;
++
++ if (sensor_conf->write) {
++ ret = sensor_conf->write(priv, sensor_conf, sensor_data,
++ (s32)val);
++ } else {
++ ret = -EOPNOTSUPP;
++ }
++
++ return ret;
++}
++
++static umode_t
++peci_cpupower_is_visible(const void *data, enum hwmon_sensor_types type,
++ u32 attr, int channel)
++{
++ struct peci_sensor_conf *sensor_conf;
++ umode_t mode = 0;
++ int ret;
++
++ if (channel >= PECI_CPUPOWER_CHANNEL_COUNT)
++ return mode;
++
++ if (attr == hwmon_power_label)
+ return 0444;
+
+- return 0;
++ ret = peci_sensor_get_ctx(attr, peci_cpupower_cfg[channel],
++ &sensor_conf, NULL, NULL,
++ ARRAY_SIZE(peci_cpupower_cfg[channel]));
++ if (!ret) {
++ if (sensor_conf->read)
++ mode |= 0444;
++ if (sensor_conf->write)
++ mode |= 0200;
++ }
++
++ return mode;
+ }
+
+-static const struct hwmon_ops cpupower_ops = {
+- .is_visible = cpupower_is_visible,
+- .read_string = cpupower_read_string,
+- .read = cpupower_read,
++static const struct hwmon_ops peci_cpupower_ops = {
++ .is_visible = peci_cpupower_is_visible,
++ .read_string = peci_cpupower_read_string,
++ .read = peci_cpupower_read,
++ .write = peci_cpupower_write,
+ };
+
+ static int peci_cpupower_probe(struct platform_device *pdev)
+@@ -170,12 +489,11 @@ static int peci_cpupower_probe(struct platform_device *pdev)
+ struct device *dev = &pdev->dev;
+ struct peci_cpupower *priv;
+ struct device *hwmon_dev;
++ u32 cmd_mask;
+
+- if ((mgr->client->adapter->cmd_mask &
+- (BIT(PECI_CMD_RD_PKG_CFG))) !=
+- (BIT(PECI_CMD_RD_PKG_CFG))) {
++ cmd_mask = BIT(PECI_CMD_RD_PKG_CFG) | BIT(PECI_CMD_WR_PKG_CFG);
++ if ((mgr->client->adapter->cmd_mask & cmd_mask) != cmd_mask)
+ return -ENODEV;
+- }
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+@@ -184,25 +502,25 @@ static int peci_cpupower_probe(struct platform_device *pdev)
+ dev_set_drvdata(dev, priv);
+ priv->mgr = mgr;
+ priv->dev = dev;
+- priv->gen_info = mgr->gen_info;
+
+ snprintf(priv->name, PECI_NAME_SIZE, "peci_cpupower.cpu%d",
+ mgr->client->addr - PECI_BASE_ADDR);
+
+- priv->power_config[priv->config_idx++] = config_table[average_power];
++ priv->power_config[priv->config_idx] = HWMON_P_LABEL |
++ peci_sensor_get_config(peci_cpupower_cfg[priv->config_idx],
++ ARRAY_SIZE(peci_cpupower_cfg
++ [priv->config_idx]));
++ priv->config_idx++;
+
+- priv->chip.ops = &cpupower_ops;
++ priv->chip.ops = &peci_cpupower_ops;
+ priv->chip.info = priv->info;
+-
+ priv->info[0] = &priv->power_info;
+
+ priv->power_info.type = hwmon_power;
+ priv->power_info.config = priv->power_config;
+
+- hwmon_dev = devm_hwmon_device_register_with_info(priv->dev,
+- priv->name,
+- priv,
+- &priv->chip,
++ hwmon_dev = devm_hwmon_device_register_with_info(priv->dev, priv->name,
++ priv, &priv->chip,
+ NULL);
+
+ if (IS_ERR(hwmon_dev))
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0115-hwmon-peci-dimmpower-implementation.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0115-hwmon-peci-dimmpower-implementation.patch
new file mode 100644
index 000000000..a1b8a5117
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0115-hwmon-peci-dimmpower-implementation.patch
@@ -0,0 +1,677 @@
+From 9a616835a8fd6bcc08fc9302957a692c1eea3d4d Mon Sep 17 00:00:00 2001
+From: Zbigniew Lukwinski <zbigniew.lukwinski@linux.intel.com>
+Date: Wed, 17 Jun 2020 08:12:27 +0200
+Subject: [PATCH] hwmon: peci: dimmpower implementation
+
+1. Peci dimmpower module implementation.
+2. Enable DIMM avarage power, power limit, power limit max setting,
+ power limit min setting reading and expose them under
+ power1_avarage, power1_cap, power1_cap_max, power1_cap_min in
+ sysfs.
+3. Enable DIMM power limit writing through power1_cap.
+
+Tested:
+ * on WilsonCity platform,
+ * power1_avarage, power1_cap, power1_cap_max and power1_cap_min work
+ as expected
+
+Signed-off-by: Zbigniew Lukwinski <zbigniew.lukwinski@linux.intel.com>
+---
+ Documentation/hwmon/index.rst | 1 +
+ Documentation/hwmon/peci-dimmpower.rst | 57 ++++
+ arch/arm/configs/aspeed_g5_defconfig | 1 +
+ drivers/hwmon/Kconfig | 14 +
+ drivers/hwmon/Makefile | 1 +
+ drivers/hwmon/peci-dimmpower.c | 502 +++++++++++++++++++++++++++++++++
+ drivers/mfd/intel-peci-client.c | 1 +
+ 7 files changed, 577 insertions(+)
+ create mode 100644 Documentation/hwmon/peci-dimmpower.rst
+ create mode 100644 drivers/hwmon/peci-dimmpower.c
+
+diff --git a/Documentation/hwmon/index.rst b/Documentation/hwmon/index.rst
+index 0bde0ef..61802e3 100644
+--- a/Documentation/hwmon/index.rst
++++ b/Documentation/hwmon/index.rst
+@@ -131,6 +131,7 @@ Hardware Monitoring Kernel Drivers
+ peci-cputemp
+ peci-dimmtemp
+ peci-cpupower
++ peci-dimmpower
+ pmbus
+ powr1220
+ pxe1610
+diff --git a/Documentation/hwmon/peci-dimmpower.rst b/Documentation/hwmon/peci-dimmpower.rst
+new file mode 100644
+index 0000000..0d9c58fd
+--- /dev/null
++++ b/Documentation/hwmon/peci-dimmpower.rst
+@@ -0,0 +1,57 @@
++.. SPDX-License-Identifier: GPL-2.0
++
++Kernel driver peci-dimmpower
++==========================
++
++:Copyright: |copy| 2020 Intel Corporation
++
++Supported chips:
++ One of Intel server CPUs listed below which is connected to a PECI bus.
++ * Intel Xeon E5/E7 v3 server processors
++ Intel Xeon E5-14xx v3 family
++ Intel Xeon E5-24xx v3 family
++ Intel Xeon E5-16xx v3 family
++ Intel Xeon E5-26xx v3 family
++ Intel Xeon E5-46xx v3 family
++ Intel Xeon E7-48xx v3 family
++ Intel Xeon E7-88xx v3 family
++ * Intel Xeon E5/E7 v4 server processors
++ Intel Xeon E5-16xx v4 family
++ Intel Xeon E5-26xx v4 family
++ Intel Xeon E5-46xx v4 family
++ Intel Xeon E7-48xx v4 family
++ Intel Xeon E7-88xx v4 family
++ * Intel Xeon Scalable server processors
++ Intel Xeon D family
++ Intel Xeon Bronze family
++ Intel Xeon Silver family
++ Intel Xeon Gold family
++ Intel Xeon Platinum family
++
++ Addresses scanned: PECI client address 0x30 - 0x37
++ Datasheet: Available from http://www.intel.com/design/literature.htm
++
++Author:
++ Zbigniew Lukwinski <zbigniew.lukwinski@linux.intel.com>
++
++Description
++-----------
++
++This driver implements a generic PECI hwmon feature which provides
++average power consumption readings of the memory basing on energy counter.
++Power value is average power since last measure given in milli Watt and
++will be measurable only when the target CPU is powered on.
++Driver provides current plane power limit, maximal and minimal power setting
++as well.
++All needed processor registers are accessible using the PECI Client Command
++Suite via the processor PECI client.
++
++``sysfs`` interface
++-------------------
++======================= =======================================================
++power1_label Provides string "dimm power".
++power1_average Provides average DRAM power since last read in milli Watt.
++power1_cap Provides current DRAM plane power limit.
++power1_cap_max Provides maximal DRAM power setting.
++power1_cap_min Provides minimal DRAM power setting.
++======================= =======================================================
+diff --git a/arch/arm/configs/aspeed_g5_defconfig b/arch/arm/configs/aspeed_g5_defconfig
+index 04c40fe..f35b81e 100644
+--- a/arch/arm/configs/aspeed_g5_defconfig
++++ b/arch/arm/configs/aspeed_g5_defconfig
+@@ -183,6 +183,7 @@ CONFIG_SENSORS_OCC_P9_SBE=y
+ CONFIG_SENSORS_PECI_CPUTEMP=y
+ CONFIG_SENSORS_PECI_DIMMTEMP=y
+ CONFIG_SENSORS_PECI_CPUPOWER=y
++CONFIG_SENSORS_PECI_DIMMPOWER=y
+ CONFIG_PMBUS=y
+ CONFIG_SENSORS_ADM1275=y
+ CONFIG_SENSORS_IBM_CFFPS=y
+diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
+index 807b489..3e229b7 100644
+--- a/drivers/hwmon/Kconfig
++++ b/drivers/hwmon/Kconfig
+@@ -1375,6 +1375,20 @@ config SENSORS_PECI_CPUPOWER
+ This driver can also be built as a module. If so, the module
+ will be called peci-cpupower.
+
++config SENSORS_PECI_DIMMPOWER
++ tristate "PECI DIMM power monitoring support"
++ depends on PECI
++ select MFD_INTEL_PECI_CLIENT
++ help
++ If you say yes here you get support for the generic Intel PECI
++ dimmpower driver which provides average engergy readings of the memory
++ package, current power limit, maximal and minimal power setting using
++ the PECI Client Command Suite via the processor PECI client.
++ Check Documentation/hwmon/peci-dimmpower for details.
++
++ This driver can also be built as a module. If so, the module
++ will be called peci-dimmpower.
++
+ source "drivers/hwmon/pmbus/Kconfig"
+
+ config SENSORS_PWM_FAN
+diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
+index fab43fd..6d2751e 100644
+--- a/drivers/hwmon/Makefile
++++ b/drivers/hwmon/Makefile
+@@ -145,6 +145,7 @@ obj-$(CONFIG_SENSORS_PCF8591) += pcf8591.o
+ obj-$(CONFIG_SENSORS_PECI_CPUTEMP) += peci-cputemp.o
+ obj-$(CONFIG_SENSORS_PECI_DIMMTEMP) += peci-dimmtemp.o
+ obj-$(CONFIG_SENSORS_PECI_CPUPOWER) += peci-cpupower.o
++obj-$(CONFIG_SENSORS_PECI_DIMMPOWER) += peci-dimmpower.o
+ obj-$(CONFIG_SENSORS_POWR1220) += powr1220.o
+ obj-$(CONFIG_SENSORS_PWM_FAN) += pwm-fan.o
+ obj-$(CONFIG_SENSORS_RASPBERRYPI_HWMON) += raspberrypi-hwmon.o
+diff --git a/drivers/hwmon/peci-dimmpower.c b/drivers/hwmon/peci-dimmpower.c
+new file mode 100644
+index 0000000..69205d8
+--- /dev/null
++++ b/drivers/hwmon/peci-dimmpower.c
+@@ -0,0 +1,502 @@
++// SPDX-License-Identifier: GPL-2.0
++// Copyright (c) 2020 Intel Corporation
++
++#include <linux/hwmon.h>
++#include <linux/jiffies.h>
++#include <linux/mfd/intel-peci-client.h>
++#include <linux/module.h>
++#include <linux/of_device.h>
++#include <linux/platform_device.h>
++#include "peci-hwmon.h"
++
++#define PECI_DIMMPOWER_CHANNEL_COUNT 1 /* Supported channels number */
++
++#define PECI_DIMMPOWER_SENSOR_COUNT 4 /* Supported sensors/readings number */
++
++struct peci_dimmpower {
++ struct device *dev;
++ struct peci_client_manager *mgr;
++ char name[PECI_NAME_SIZE];
++ u32 power_config[PECI_DIMMPOWER_CHANNEL_COUNT + 1];
++ u32 config_idx;
++ struct hwmon_channel_info power_info;
++ const struct hwmon_channel_info *info[2];
++ struct hwmon_chip_info chip;
++
++ struct peci_sensor_data
++ sensor_data_list[PECI_DIMMPOWER_CHANNEL_COUNT]
++ [PECI_DIMMPOWER_SENSOR_COUNT];
++
++ s32 avg_power_val;
++ union peci_pkg_power_sku_unit units;
++ bool units_valid;
++
++ u32 dpl_time_window;
++ bool dpl_time_window_valid;
++};
++
++static const char *peci_dimmpower_labels[PECI_DIMMPOWER_CHANNEL_COUNT] = {
++ "dimm power",
++};
++
++/**
++ * peci_dimmpower_read_dram_power_limit - read PCS DRAM Power Limit
++ * @peci_mgr: PECI client manager handle
++ * @reg: Pointer to the variable read value is going to be put
++ *
++ * Return: 0 if succeeded, other values in case an error.
++ */
++static inline int
++peci_dimmpower_read_dram_power_limit(struct peci_client_manager *peci_mgr,
++ union peci_dram_power_limit *reg)
++{
++ return peci_pcs_read(peci_mgr, PECI_MBX_INDEX_DDR_RAPL_PL1,
++ PECI_PCS_PARAM_ZERO, &reg->value);
++}
++
++static int
++peci_dimmpower_get_avg_power(void *ctx, struct peci_sensor_conf *sensor_conf,
++ struct peci_sensor_data *sensor_data,
++ s32 *val)
++{
++ struct peci_dimmpower *priv = (struct peci_dimmpower *)ctx;
++ u32 energy_cnt;
++ ulong jif;
++ int ret;
++
++ if (!peci_sensor_need_update_with_time(sensor_data,
++ sensor_conf->update_interval)) {
++ *val = priv->avg_power_val;
++ dev_dbg(priv->dev, "skip reading peci, average power %dmW\n",
++ *val);
++ return 0;
++ }
++
++ ret = peci_pcs_get_units(priv->mgr, &priv->units, &priv->units_valid);
++ if (ret) {
++ dev_dbg(priv->dev, "not able to read units\n");
++ return ret;
++ }
++
++ jif = jiffies;
++ ret = peci_pcs_read(priv->mgr, PECI_MBX_INDEX_ENERGY_STATUS,
++ PECI_PKG_ID_DIMM, &energy_cnt);
++ if (ret) {
++ dev_dbg(priv->dev, "not able to read energy\n");
++ return ret;
++ }
++
++ ret = peci_pcs_calc_pwr_from_eng(priv->dev, sensor_data, energy_cnt,
++ priv->units.bits.eng_unit, val);
++
++ priv->avg_power_val = *val;
++ peci_sensor_mark_updated_with_time(sensor_data, jif);
++
++ dev_dbg(priv->dev, "average power %dmW, jif %lu, HZ is %d jiffies\n",
++ *val, jif, HZ);
++
++ return ret;
++}
++
++static int
++peci_dimmpower_get_power_limit(void *ctx, struct peci_sensor_conf *sensor_conf,
++ struct peci_sensor_data *sensor_data,
++ s32 *val)
++{
++ struct peci_dimmpower *priv = (struct peci_dimmpower *)ctx;
++ union peci_dram_power_limit power_limit;
++ ulong jif;
++ int ret;
++
++ if (!peci_sensor_need_update_with_time(sensor_data,
++ sensor_conf->update_interval)) {
++ *val = sensor_data->value;
++ dev_dbg(priv->dev, "skip reading peci, power limit %dmW\n",
++ *val);
++ return 0;
++ }
++
++ ret = peci_pcs_get_units(priv->mgr, &priv->units, &priv->units_valid);
++ if (ret) {
++ dev_dbg(priv->dev, "not able to read units\n");
++ return ret;
++ }
++
++ jif = jiffies;
++ ret = peci_dimmpower_read_dram_power_limit(priv->mgr, &power_limit);
++ if (ret) {
++ dev_dbg(priv->dev, "not able to read power limit\n");
++ return ret;
++ }
++
++ *val = peci_pcs_xn_to_munits(power_limit.bits.pp_pwr_lim,
++ priv->units.bits.pwr_unit);
++
++ sensor_data->value = *val;
++ peci_sensor_mark_updated_with_time(sensor_data, jif);
++
++ dev_dbg(priv->dev, "raw power limit %u, unit %u, power limit %d\n",
++ power_limit.bits.pp_pwr_lim, priv->units.bits.pwr_unit, *val);
++
++ return ret;
++}
++
++static int
++peci_dimmpower_set_power_limit(void *ctx, struct peci_sensor_conf *sensor_conf,
++ struct peci_sensor_data *sensor_data,
++ s32 val)
++{
++ struct peci_dimmpower *priv = (struct peci_dimmpower *)ctx;
++ union peci_dram_power_limit power_limit;
++ int ret;
++
++ ret = peci_pcs_get_units(priv->mgr, &priv->units, &priv->units_valid);
++ if (ret) {
++ dev_dbg(priv->dev, "not able to read units\n");
++ return ret;
++ }
++
++ ret = peci_dimmpower_read_dram_power_limit(priv->mgr, &power_limit);
++ if (ret) {
++ dev_dbg(priv->dev, "not able to read power limit\n");
++ return ret;
++ }
++
++ /* Calculate DPL time window if needed */
++ if (!priv->dpl_time_window_valid) {
++ priv->dpl_time_window =
++ peci_pcs_calc_plxy_time_window(peci_pcs_munits_to_xn(
++ PECI_PCS_PPL1_TIME_WINDOW,
++ priv->units.bits.tim_unit));
++ priv->dpl_time_window_valid = true;
++ }
++
++ /* Enable or disable power limitation */
++ if (val > 0) {
++ power_limit.bits.pp_pwr_lim =
++ peci_pcs_munits_to_xn(val, priv->units.bits.pwr_unit);
++ power_limit.bits.pwr_lim_ctrl_en = 1u;
++ power_limit.bits.ctrl_time_win = priv->dpl_time_window;
++ } else {
++ power_limit.bits.pp_pwr_lim = 0u;
++ power_limit.bits.pwr_lim_ctrl_en = 0u;
++ }
++
++ ret = peci_pcs_write(priv->mgr, PECI_MBX_INDEX_DDR_RAPL_PL1,
++ PECI_PCS_PARAM_ZERO, power_limit.value);
++ if (ret) {
++ dev_dbg(priv->dev, "not able to write power limit\n");
++ return ret;
++ }
++
++ dev_dbg(priv->dev, "power limit %d, unit %u, raw power limit %u,\n",
++ val, priv->units.bits.pwr_unit, power_limit.bits.pp_pwr_lim);
++
++ return ret;
++}
++
++static int
++peci_dimmpower_read_max_power(void *ctx, struct peci_sensor_conf *sensor_conf,
++ struct peci_sensor_data *sensor_data,
++ s32 *val)
++{
++ struct peci_dimmpower *priv = (struct peci_dimmpower *)ctx;
++ union peci_dram_power_info_high power_info;
++ ulong jif;
++ int ret;
++
++ if (!peci_sensor_need_update_with_time(sensor_data,
++ sensor_conf->update_interval)) {
++ *val = sensor_data->value;
++ dev_dbg(priv->dev, "skip reading peci, max power %dmW\n",
++ *val);
++ return 0;
++ }
++
++ ret = peci_pcs_get_units(priv->mgr, &priv->units, &priv->units_valid);
++ if (ret) {
++ dev_dbg(priv->dev, "not able to read units\n");
++ return ret;
++ }
++
++ jif = jiffies;
++ ret = peci_pcs_read(priv->mgr, PECI_MBX_INDEX_DDR_PWR_INFO_HIGH,
++ PECI_PCS_PARAM_ZERO, &power_info.value);
++ if (ret) {
++ dev_dbg(priv->dev, "not able to read power info\n");
++ return ret;
++ }
++
++ *val = peci_pcs_xn_to_munits(power_info.bits.max_pwr,
++ priv->units.bits.pwr_unit);
++
++ sensor_data->value = *val;
++ peci_sensor_mark_updated_with_time(sensor_data, jif);
++
++ dev_dbg(priv->dev, "raw max power %u, unit %u, max power %dmW\n",
++ power_info.bits.max_pwr, priv->units.bits.pwr_unit, *val);
++
++ return ret;
++}
++
++static int
++peci_dimmpower_read_min_power(void *ctx, struct peci_sensor_conf *sensor_conf,
++ struct peci_sensor_data *sensor_data,
++ s32 *val)
++{
++ struct peci_dimmpower *priv = (struct peci_dimmpower *)ctx;
++ union peci_dram_power_info_low power_info;
++ ulong jif;
++ int ret;
++
++ if (!peci_sensor_need_update_with_time(sensor_data,
++ sensor_conf->update_interval)) {
++ *val = sensor_data->value;
++ dev_dbg(priv->dev, "skip reading peci, min power %dmW\n",
++ *val);
++ return 0;
++ }
++
++ ret = peci_pcs_get_units(priv->mgr, &priv->units, &priv->units_valid);
++ if (ret) {
++ dev_dbg(priv->dev, "not able to read units\n");
++ return ret;
++ }
++
++ jif = jiffies;
++ ret = peci_pcs_read(priv->mgr, PECI_MBX_INDEX_DDR_PWR_INFO_LOW,
++ PECI_PCS_PARAM_ZERO, &power_info.value);
++ if (ret) {
++ dev_dbg(priv->dev, "not able to read power info\n");
++ return ret;
++ }
++
++ *val = peci_pcs_xn_to_munits(power_info.bits.min_pwr,
++ priv->units.bits.pwr_unit);
++
++ sensor_data->value = *val;
++ peci_sensor_mark_updated_with_time(sensor_data, jif);
++
++ dev_dbg(priv->dev, "raw min power %u, unit %u, min power %dmW\n",
++ power_info.bits.min_pwr, priv->units.bits.pwr_unit, *val);
++
++ return ret;
++}
++
++static struct peci_sensor_conf
++peci_dimmpower_cfg[PECI_DIMMPOWER_CHANNEL_COUNT]
++ [PECI_DIMMPOWER_SENSOR_COUNT] = {
++ /* Channel 0 - Power */
++ {
++ {
++ .attribute = hwmon_power_average,
++ .config = HWMON_P_AVERAGE,
++ .update_interval = UPDATE_INTERVAL_100MS,
++ .read = peci_dimmpower_get_avg_power,
++ .write = NULL,
++ },
++ {
++ .attribute = hwmon_power_cap,
++ .config = HWMON_P_CAP,
++ .update_interval = UPDATE_INTERVAL_100MS,
++ .read = peci_dimmpower_get_power_limit,
++ .write = peci_dimmpower_set_power_limit,
++ },
++ {
++ .attribute = hwmon_power_cap_max,
++ .config = HWMON_P_CAP_MAX,
++ .update_interval = UPDATE_INTERVAL_10S,
++ .read = peci_dimmpower_read_max_power,
++ .write = NULL,
++ },
++ {
++ .attribute = hwmon_power_cap_min,
++ .config = HWMON_P_CAP_MIN,
++ .update_interval = UPDATE_INTERVAL_10S,
++ .read = peci_dimmpower_read_min_power,
++ .write = NULL,
++ },
++ },
++};
++
++static int
++peci_dimmpower_read_string(struct device *dev, enum hwmon_sensor_types type,
++ u32 attr, int channel, const char **str)
++{
++ if (attr != hwmon_power_label ||
++ channel >= PECI_DIMMPOWER_CHANNEL_COUNT)
++ return -EOPNOTSUPP;
++
++ if (str)
++ *str = peci_dimmpower_labels[channel];
++ else
++ return -EINVAL;
++
++ return 0;
++}
++
++static int
++peci_dimmpower_read(struct device *dev, enum hwmon_sensor_types type,
++ u32 attr, int channel, long *val)
++{
++ struct peci_dimmpower *priv = dev_get_drvdata(dev);
++ struct peci_sensor_conf *sensor_conf;
++ struct peci_sensor_data *sensor_data;
++ int ret;
++
++ if (!priv || !val)
++ return -EINVAL;
++
++ if (channel >= PECI_DIMMPOWER_CHANNEL_COUNT)
++ return -EOPNOTSUPP;
++
++ ret = peci_sensor_get_ctx(attr, peci_dimmpower_cfg[channel],
++ &sensor_conf, priv->sensor_data_list[channel],
++ &sensor_data,
++ ARRAY_SIZE(peci_dimmpower_cfg[channel]));
++ if (ret)
++ return ret;
++
++ if (sensor_conf->read) {
++ s32 tmp;
++
++ ret = sensor_conf->read(priv, sensor_conf, sensor_data, &tmp);
++ if (!ret)
++ *val = (long)tmp;
++ } else {
++ ret = -EOPNOTSUPP;
++ }
++
++ return ret;
++}
++
++static int
++peci_dimmpower_write(struct device *dev, enum hwmon_sensor_types type,
++ u32 attr, int channel, long val)
++{
++ struct peci_dimmpower *priv = dev_get_drvdata(dev);
++ struct peci_sensor_conf *sensor_conf;
++ struct peci_sensor_data *sensor_data;
++ int ret;
++
++ if (!priv)
++ return -EINVAL;
++
++ if (channel >= PECI_DIMMPOWER_CHANNEL_COUNT)
++ return -EOPNOTSUPP;
++
++ ret = peci_sensor_get_ctx(attr, peci_dimmpower_cfg[channel],
++ &sensor_conf, priv->sensor_data_list[channel],
++ &sensor_data,
++ ARRAY_SIZE(peci_dimmpower_cfg[channel]));
++ if (ret)
++ return ret;
++
++ if (sensor_conf->write) {
++ ret = sensor_conf->write(priv, sensor_conf, sensor_data,
++ (s32)val);
++ } else {
++ ret = -EOPNOTSUPP;
++ }
++
++ return ret;
++}
++
++static umode_t
++peci_dimmpower_is_visible(const void *data, enum hwmon_sensor_types type,
++ u32 attr, int channel)
++{
++ struct peci_sensor_conf *sensor_conf;
++ umode_t mode = 0;
++ int ret;
++
++ if (channel >= PECI_DIMMPOWER_CHANNEL_COUNT)
++ return mode;
++
++ if (attr == hwmon_power_label)
++ return 0444;
++
++ ret = peci_sensor_get_ctx(attr, peci_dimmpower_cfg[channel],
++ &sensor_conf, NULL, NULL,
++ ARRAY_SIZE(peci_dimmpower_cfg[channel]));
++ if (!ret) {
++ if (sensor_conf->read)
++ mode |= 0444;
++ if (sensor_conf->write)
++ mode |= 0200;
++ }
++
++ return mode;
++}
++
++static const struct hwmon_ops peci_dimmpower_ops = {
++ .is_visible = peci_dimmpower_is_visible,
++ .read_string = peci_dimmpower_read_string,
++ .read = peci_dimmpower_read,
++ .write = peci_dimmpower_write,
++};
++
++static int peci_dimmpower_probe(struct platform_device *pdev)
++{
++ struct peci_client_manager *mgr = dev_get_drvdata(pdev->dev.parent);
++ struct device *dev = &pdev->dev;
++ struct peci_dimmpower *priv;
++ struct device *hwmon_dev;
++ u32 cmd_mask;
++
++ cmd_mask = BIT(PECI_CMD_RD_PKG_CFG) | BIT(PECI_CMD_WR_PKG_CFG);
++ if ((mgr->client->adapter->cmd_mask & cmd_mask) != cmd_mask)
++ return -ENODEV;
++
++ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
++ if (!priv)
++ return -ENOMEM;
++
++ dev_set_drvdata(dev, priv);
++ priv->mgr = mgr;
++ priv->dev = dev;
++
++ snprintf(priv->name, PECI_NAME_SIZE, "peci_dimmpower.cpu%d",
++ mgr->client->addr - PECI_BASE_ADDR);
++
++ priv->power_config[priv->config_idx] = HWMON_P_LABEL |
++ peci_sensor_get_config(peci_dimmpower_cfg[priv->config_idx],
++ ARRAY_SIZE(peci_dimmpower_cfg
++ [priv->config_idx]));
++ priv->config_idx++;
++
++ priv->chip.ops = &peci_dimmpower_ops;
++ priv->chip.info = priv->info;
++ priv->info[0] = &priv->power_info;
++
++ priv->power_info.type = hwmon_power;
++ priv->power_info.config = priv->power_config;
++
++ hwmon_dev = devm_hwmon_device_register_with_info(priv->dev, priv->name,
++ priv, &priv->chip,
++ NULL);
++
++ if (IS_ERR(hwmon_dev))
++ return PTR_ERR(hwmon_dev);
++
++ dev_dbg(dev, "%s: sensor '%s'\n", dev_name(hwmon_dev), priv->name);
++
++ return 0;
++}
++
++static const struct platform_device_id peci_dimmpower_ids[] = {
++ { .name = "peci-dimmpower", .driver_data = 0 },
++ { }
++};
++MODULE_DEVICE_TABLE(platform, peci_dimmpower_ids);
++
++static struct platform_driver peci_dimmpower_driver = {
++ .probe = peci_dimmpower_probe,
++ .id_table = peci_dimmpower_ids,
++ .driver = { .name = KBUILD_MODNAME, },
++};
++module_platform_driver(peci_dimmpower_driver);
++
++MODULE_AUTHOR("Zbigniew Lukwinski <zbigniew.lukwinski@linux.intel.com>");
++MODULE_DESCRIPTION("PECI dimmpower driver");
++MODULE_LICENSE("GPL v2");
+diff --git a/drivers/mfd/intel-peci-client.c b/drivers/mfd/intel-peci-client.c
+index f0e8ecc..84e5be0 100644
+--- a/drivers/mfd/intel-peci-client.c
++++ b/drivers/mfd/intel-peci-client.c
+@@ -22,6 +22,7 @@ static struct mfd_cell peci_functions[] = {
+ { .name = "peci-cputemp", },
+ { .name = "peci-dimmtemp", },
+ { .name = "peci-cpupower", },
++ { .name = "peci-dimmpower", },
+ };
+
+ static const struct cpu_gen_info cpu_gen_info_table[] = {
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2019-19770/0001-blktrace-fix-debugfs-use-after-free.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2019-19770/0001-blktrace-fix-debugfs-use-after-free.patch
new file mode 100644
index 000000000..a455a43c5
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2019-19770/0001-blktrace-fix-debugfs-use-after-free.patch
@@ -0,0 +1,214 @@
+From 1e1cea6eb8838117f676aaf6e0a465dd6a9addad Mon Sep 17 00:00:00 2001
+From: Luis Chamberlain <mcgrof@kernel.org>
+Date: Fri, 19 Jun 2020 20:47:28 +0000
+Subject: [PATCH] blktrace: fix debugfs use after free
+
+On commit 6ac93117ab00 ("blktrace: use existing disk debugfs directory")
+merged on v4.12 Omar fixed the original blktrace code for request-based
+drivers (multiqueue). This however left in place a possible crash, if you
+happen to abuse blktrace while racing to remove / add a device.
+
+We used to use asynchronous removal of the request_queue, and with that
+the issue was easier to reproduce. Now that we have reverted to
+synchronous removal of the request_queue, the issue is still possible to
+reproduce, its however just a bit more difficult.
+
+We essentially run two instances of break-blktrace which add/remove
+a loop device, and setup a blktrace and just never tear the blktrace
+down. We do this twice in parallel. This is easily reproduced with the
+script run_0004.sh from break-blktrace [0].
+
+We can end up with two types of panics each reflecting where we
+race, one a failed blktrace setup:
+
+[ 252.426751] debugfs: Directory 'loop0' with parent 'block' already present!
+[ 252.432265] BUG: kernel NULL pointer dereference, address: 00000000000000a0
+[ 252.436592] #PF: supervisor write access in kernel mode
+[ 252.439822] #PF: error_code(0x0002) - not-present page
+[ 252.442967] PGD 0 P4D 0
+[ 252.444656] Oops: 0002 [#1] SMP NOPTI
+[ 252.446972] CPU: 10 PID: 1153 Comm: break-blktrace Tainted: G E 5.7.0-rc2-next-20200420+ #164
+[ 252.452673] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.13.0-1 04/01/2014
+[ 252.456343] RIP: 0010:down_write+0x15/0x40
+[ 252.458146] Code: eb ca e8 ae 22 8d ff cc cc cc cc cc cc cc cc cc cc cc cc
+ cc cc 0f 1f 44 00 00 55 48 89 fd e8 52 db ff ff 31 c0 ba 01 00
+ 00 00 <f0> 48 0f b1 55 00 75 0f 48 8b 04 25 c0 8b 01 00 48 89
+ 45 08 5d
+[ 252.463638] RSP: 0018:ffffa626415abcc8 EFLAGS: 00010246
+[ 252.464950] RAX: 0000000000000000 RBX: ffff958c25f0f5c0 RCX: ffffff8100000000
+[ 252.466727] RDX: 0000000000000001 RSI: ffffff8100000000 RDI: 00000000000000a0
+[ 252.468482] RBP: 00000000000000a0 R08: 0000000000000000 R09: 0000000000000001
+[ 252.470014] R10: 0000000000000000 R11: ffff958d1f9227ff R12: 0000000000000000
+[ 252.471473] R13: ffff958c25ea5380 R14: ffffffff8cce15f1 R15: 00000000000000a0
+[ 252.473346] FS: 00007f2e69dee540(0000) GS:ffff958c2fc80000(0000) knlGS:0000000000000000
+[ 252.475225] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+[ 252.476267] CR2: 00000000000000a0 CR3: 0000000427d10004 CR4: 0000000000360ee0
+[ 252.477526] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
+[ 252.478776] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
+[ 252.479866] Call Trace:
+[ 252.480322] simple_recursive_removal+0x4e/0x2e0
+[ 252.481078] ? debugfs_remove+0x60/0x60
+[ 252.481725] ? relay_destroy_buf+0x77/0xb0
+[ 252.482662] debugfs_remove+0x40/0x60
+[ 252.483518] blk_remove_buf_file_callback+0x5/0x10
+[ 252.484328] relay_close_buf+0x2e/0x60
+[ 252.484930] relay_open+0x1ce/0x2c0
+[ 252.485520] do_blk_trace_setup+0x14f/0x2b0
+[ 252.486187] __blk_trace_setup+0x54/0xb0
+[ 252.486803] blk_trace_ioctl+0x90/0x140
+[ 252.487423] ? do_sys_openat2+0x1ab/0x2d0
+[ 252.488053] blkdev_ioctl+0x4d/0x260
+[ 252.488636] block_ioctl+0x39/0x40
+[ 252.489139] ksys_ioctl+0x87/0xc0
+[ 252.489675] __x64_sys_ioctl+0x16/0x20
+[ 252.490380] do_syscall_64+0x52/0x180
+[ 252.491032] entry_SYSCALL_64_after_hwframe+0x44/0xa9
+
+And the other on the device removal:
+
+[ 128.528940] debugfs: Directory 'loop0' with parent 'block' already present!
+[ 128.615325] BUG: kernel NULL pointer dereference, address: 00000000000000a0
+[ 128.619537] #PF: supervisor write access in kernel mode
+[ 128.622700] #PF: error_code(0x0002) - not-present page
+[ 128.625842] PGD 0 P4D 0
+[ 128.627585] Oops: 0002 [#1] SMP NOPTI
+[ 128.629871] CPU: 12 PID: 544 Comm: break-blktrace Tainted: G E 5.7.0-rc2-next-20200420+ #164
+[ 128.635595] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.13.0-1 04/01/2014
+[ 128.640471] RIP: 0010:down_write+0x15/0x40
+[ 128.643041] Code: eb ca e8 ae 22 8d ff cc cc cc cc cc cc cc cc cc cc cc cc
+ cc cc 0f 1f 44 00 00 55 48 89 fd e8 52 db ff ff 31 c0 ba 01 00
+ 00 00 <f0> 48 0f b1 55 00 75 0f 65 48 8b 04 25 c0 8b 01 00 48 89
+ 45 08 5d
+[ 128.650180] RSP: 0018:ffffa9c3c05ebd78 EFLAGS: 00010246
+[ 128.651820] RAX: 0000000000000000 RBX: ffff8ae9a6370240 RCX: ffffff8100000000
+[ 128.653942] RDX: 0000000000000001 RSI: ffffff8100000000 RDI: 00000000000000a0
+[ 128.655720] RBP: 00000000000000a0 R08: 0000000000000002 R09: ffff8ae9afd2d3d0
+[ 128.657400] R10: 0000000000000056 R11: 0000000000000000 R12: 0000000000000000
+[ 128.659099] R13: 0000000000000000 R14: 0000000000000003 R15: 00000000000000a0
+[ 128.660500] FS: 00007febfd995540(0000) GS:ffff8ae9afd00000(0000) knlGS:0000000000000000
+[ 128.662204] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+[ 128.663426] CR2: 00000000000000a0 CR3: 0000000420042003 CR4: 0000000000360ee0
+[ 128.664776] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
+[ 128.666022] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
+[ 128.667282] Call Trace:
+[ 128.667801] simple_recursive_removal+0x4e/0x2e0
+[ 128.668663] ? debugfs_remove+0x60/0x60
+[ 128.669368] debugfs_remove+0x40/0x60
+[ 128.669985] blk_trace_free+0xd/0x50
+[ 128.670593] __blk_trace_remove+0x27/0x40
+[ 128.671274] blk_trace_shutdown+0x30/0x40
+[ 128.671935] blk_release_queue+0x95/0xf0
+[ 128.672589] kobject_put+0xa5/0x1b0
+[ 128.673188] disk_release+0xa2/0xc0
+[ 128.673786] device_release+0x28/0x80
+[ 128.674376] kobject_put+0xa5/0x1b0
+[ 128.674915] loop_remove+0x39/0x50 [loop]
+[ 128.675511] loop_control_ioctl+0x113/0x130 [loop]
+[ 128.676199] ksys_ioctl+0x87/0xc0
+[ 128.676708] __x64_sys_ioctl+0x16/0x20
+[ 128.677274] do_syscall_64+0x52/0x180
+[ 128.677823] entry_SYSCALL_64_after_hwframe+0x44/0xa9
+
+The common theme here is:
+
+debugfs: Directory 'loop0' with parent 'block' already present
+
+This crash happens because of how blktrace uses the debugfs directory
+where it places its files. Upon init we always create the same directory
+which would be needed by blktrace but we only do this for make_request
+drivers (multiqueue) block drivers. When you race a removal of these
+devices with a blktrace setup you end up in a situation where the
+make_request recursive debugfs removal will sweep away the blktrace
+files and then later blktrace will also try to remove individual
+dentries which are already NULL. The inverse is also possible and hence
+the two types of use after frees.
+
+We don't create the block debugfs directory on init for these types of
+block devices:
+
+ * request-based block driver block devices
+ * every possible partition
+ * scsi-generic
+
+And so, this race should in theory only be possible with make_request
+drivers.
+
+We can fix the UAF by simply re-using the debugfs directory for
+make_request drivers (multiqueue) and only creating the ephemeral
+directory for the other type of block devices. The new clarifications
+on relying on the q->blk_trace_mutex *and* also checking for q->blk_trace
+*prior* to processing a blktrace ensures the debugfs directories are
+only created if no possible directory name clashes are possible.
+
+This goes tested with:
+
+ o nvme partitions
+ o ISCSI with tgt, and blktracing against scsi-generic with:
+ o block
+ o tape
+ o cdrom
+ o media changer
+ o blktests
+
+This patch is part of the work which disputes the severity of
+CVE-2019-19770 which shows this issue is not a core debugfs issue, but
+a misuse of debugfs within blktace.
+
+Fixes: 6ac93117ab00 ("blktrace: use existing disk debugfs directory")
+Reported-by: syzbot+603294af2d01acfdd6da@syzkaller.appspotmail.com
+Signed-off-by: Luis Chamberlain <mcgrof@kernel.org>
+Reviewed-by: Christoph Hellwig <hch@lst.de>
+Cc: Bart Van Assche <bvanassche@acm.org>
+Cc: Omar Sandoval <osandov@fb.com>
+Cc: Hannes Reinecke <hare@suse.com>
+Cc: Nicolai Stange <nstange@suse.de>
+Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Cc: Michal Hocko <mhocko@kernel.org>
+Cc: "Martin K. Petersen" <martin.petersen@oracle.com>
+Cc: "James E.J. Bottomley" <jejb@linux.ibm.com>
+Cc: yu kuai <yukuai3@huawei.com>
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+---
+ kernel/trace/blktrace.c | 18 ++++++++++++------
+ 1 file changed, 12 insertions(+), 6 deletions(-)
+
+diff --git a/kernel/trace/blktrace.c b/kernel/trace/blktrace.c
+index e7e483cdbea6..fc2ad395c61d 100644
+--- a/kernel/trace/blktrace.c
++++ b/kernel/trace/blktrace.c
+@@ -508,10 +508,18 @@ static int do_blk_trace_setup(struct request_queue *q, char *name, dev_t dev,
+ if (!bt->msg_data)
+ goto err;
+
+- ret = -ENOENT;
+-
+- dir = debugfs_lookup(buts->name, blk_debugfs_root);
+- if (!dir)
++#ifdef CONFIG_BLK_DEBUG_FS
++ /*
++ * When tracing whole make_request drivers (multiqueue) block devices,
++ * reuse the existing debugfs directory created by the block layer on
++ * init. For request-based block devices, all partitions block devices,
++ * and scsi-generic block devices we create a temporary new debugfs
++ * directory that will be removed once the trace ends.
++ */
++ if (queue_is_mq(q) && bdev && bdev == bdev->bd_contains)
++ dir = q->debugfs_dir;
++ else
++#endif
+ bt->dir = dir = debugfs_create_dir(buts->name, blk_debugfs_root);
+
+ bt->dev = dev;
+@@ -552,8 +560,6 @@ static int do_blk_trace_setup(struct request_queue *q, char *name, dev_t dev,
+
+ ret = 0;
+ err:
+- if (dir && !bt->dir)
+- dput(dir);
+ if (ret)
+ blk_trace_free(bt);
+ return ret;
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2020-14356/0001-cgroup-fix-cgroup_sk_alloc-for-sk_clone_lock.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2020-14356/0001-cgroup-fix-cgroup_sk_alloc-for-sk_clone_lock.patch
new file mode 100644
index 000000000..dd4fea693
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2020-14356/0001-cgroup-fix-cgroup_sk_alloc-for-sk_clone_lock.patch
@@ -0,0 +1,178 @@
+From ad0f75e5f57ccbceec13274e1e242f2b5a6397ed Mon Sep 17 00:00:00 2001
+From: Cong Wang <xiyou.wangcong@gmail.com>
+Date: Thu, 2 Jul 2020 11:52:56 -0700
+Subject: [PATCH] cgroup: fix cgroup_sk_alloc() for sk_clone_lock()
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+When we clone a socket in sk_clone_lock(), its sk_cgrp_data is
+copied, so the cgroup refcnt must be taken too. And, unlike the
+sk_alloc() path, sock_update_netprioidx() is not called here.
+Therefore, it is safe and necessary to grab the cgroup refcnt
+even when cgroup_sk_alloc is disabled.
+
+sk_clone_lock() is in BH context anyway, the in_interrupt()
+would terminate this function if called there. And for sk_alloc()
+skcd->val is always zero. So it's safe to factor out the code
+to make it more readable.
+
+The global variable 'cgroup_sk_alloc_disabled' is used to determine
+whether to take these reference counts. It is impossible to make
+the reference counting correct unless we save this bit of information
+in skcd->val. So, add a new bit there to record whether the socket
+has already taken the reference counts. This obviously relies on
+kmalloc() to align cgroup pointers to at least 4 bytes,
+ARCH_KMALLOC_MINALIGN is certainly larger than that.
+
+This bug seems to be introduced since the beginning, commit
+d979a39d7242 ("cgroup: duplicate cgroup reference when cloning sockets")
+tried to fix it but not compeletely. It seems not easy to trigger until
+the recent commit 090e28b229af
+("netprio_cgroup: Fix unlimited memory leak of v2 cgroups") was merged.
+
+Fixes: bd1060a1d671 ("sock, cgroup: add sock->sk_cgroup")
+Reported-by: Cameron Berkenpas <cam@neo-zeon.de>
+Reported-by: Peter Geis <pgwipeout@gmail.com>
+Reported-by: Lu Fengqi <lufq.fnst@cn.fujitsu.com>
+Reported-by: Daniël Sonck <dsonck92@gmail.com>
+Reported-by: Zhang Qiang <qiang.zhang@windriver.com>
+Tested-by: Cameron Berkenpas <cam@neo-zeon.de>
+Tested-by: Peter Geis <pgwipeout@gmail.com>
+Tested-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
+Cc: Daniel Borkmann <daniel@iogearbox.net>
+Cc: Zefan Li <lizefan@huawei.com>
+Cc: Tejun Heo <tj@kernel.org>
+Cc: Roman Gushchin <guro@fb.com>
+Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+---
+ include/linux/cgroup-defs.h | 6 ++++--
+ include/linux/cgroup.h | 4 +++-
+ kernel/cgroup/cgroup.c | 31 +++++++++++++++++++------------
+ net/core/sock.c | 2 +-
+ 4 files changed, 27 insertions(+), 16 deletions(-)
+
+diff --git a/include/linux/cgroup-defs.h b/include/linux/cgroup-defs.h
+index 52661155f85f..4f1cd0edc57d 100644
+--- a/include/linux/cgroup-defs.h
++++ b/include/linux/cgroup-defs.h
+@@ -790,7 +790,8 @@ struct sock_cgroup_data {
+ union {
+ #ifdef __LITTLE_ENDIAN
+ struct {
+- u8 is_data;
++ u8 is_data : 1;
++ u8 no_refcnt : 1;
+ u8 padding;
+ u16 prioidx;
+ u32 classid;
+@@ -800,7 +801,8 @@ struct sock_cgroup_data {
+ u32 classid;
+ u16 prioidx;
+ u8 padding;
+- u8 is_data;
++ u8 no_refcnt : 1;
++ u8 is_data : 1;
+ } __packed;
+ #endif
+ u64 val;
+diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h
+index 4598e4da6b1b..618838c48313 100644
+--- a/include/linux/cgroup.h
++++ b/include/linux/cgroup.h
+@@ -822,6 +822,7 @@ extern spinlock_t cgroup_sk_update_lock;
+
+ void cgroup_sk_alloc_disable(void);
+ void cgroup_sk_alloc(struct sock_cgroup_data *skcd);
++void cgroup_sk_clone(struct sock_cgroup_data *skcd);
+ void cgroup_sk_free(struct sock_cgroup_data *skcd);
+
+ static inline struct cgroup *sock_cgroup_ptr(struct sock_cgroup_data *skcd)
+@@ -835,7 +836,7 @@ static inline struct cgroup *sock_cgroup_ptr(struct sock_cgroup_data *skcd)
+ */
+ v = READ_ONCE(skcd->val);
+
+- if (v & 1)
++ if (v & 3)
+ return &cgrp_dfl_root.cgrp;
+
+ return (struct cgroup *)(unsigned long)v ?: &cgrp_dfl_root.cgrp;
+@@ -847,6 +848,7 @@ static inline struct cgroup *sock_cgroup_ptr(struct sock_cgroup_data *skcd)
+ #else /* CONFIG_CGROUP_DATA */
+
+ static inline void cgroup_sk_alloc(struct sock_cgroup_data *skcd) {}
++static inline void cgroup_sk_clone(struct sock_cgroup_data *skcd) {}
+ static inline void cgroup_sk_free(struct sock_cgroup_data *skcd) {}
+
+ #endif /* CONFIG_CGROUP_DATA */
+diff --git a/kernel/cgroup/cgroup.c b/kernel/cgroup/cgroup.c
+index 1ea181a58465..dd247747ec14 100644
+--- a/kernel/cgroup/cgroup.c
++++ b/kernel/cgroup/cgroup.c
+@@ -6439,18 +6439,8 @@ void cgroup_sk_alloc_disable(void)
+
+ void cgroup_sk_alloc(struct sock_cgroup_data *skcd)
+ {
+- if (cgroup_sk_alloc_disabled)
+- return;
+-
+- /* Socket clone path */
+- if (skcd->val) {
+- /*
+- * We might be cloning a socket which is left in an empty
+- * cgroup and the cgroup might have already been rmdir'd.
+- * Don't use cgroup_get_live().
+- */
+- cgroup_get(sock_cgroup_ptr(skcd));
+- cgroup_bpf_get(sock_cgroup_ptr(skcd));
++ if (cgroup_sk_alloc_disabled) {
++ skcd->no_refcnt = 1;
+ return;
+ }
+
+@@ -6475,10 +6465,27 @@ void cgroup_sk_alloc(struct sock_cgroup_data *skcd)
+ rcu_read_unlock();
+ }
+
++void cgroup_sk_clone(struct sock_cgroup_data *skcd)
++{
++ if (skcd->val) {
++ if (skcd->no_refcnt)
++ return;
++ /*
++ * We might be cloning a socket which is left in an empty
++ * cgroup and the cgroup might have already been rmdir'd.
++ * Don't use cgroup_get_live().
++ */
++ cgroup_get(sock_cgroup_ptr(skcd));
++ cgroup_bpf_get(sock_cgroup_ptr(skcd));
++ }
++}
++
+ void cgroup_sk_free(struct sock_cgroup_data *skcd)
+ {
+ struct cgroup *cgrp = sock_cgroup_ptr(skcd);
+
++ if (skcd->no_refcnt)
++ return;
+ cgroup_bpf_put(cgrp);
+ cgroup_put(cgrp);
+ }
+diff --git a/net/core/sock.c b/net/core/sock.c
+index d832c650287c..2e5b7870e5d3 100644
+--- a/net/core/sock.c
++++ b/net/core/sock.c
+@@ -1926,7 +1926,7 @@ struct sock *sk_clone_lock(const struct sock *sk, const gfp_t priority)
+ /* sk->sk_memcg will be populated at accept() time */
+ newsk->sk_memcg = NULL;
+
+- cgroup_sk_alloc(&newsk->sk_cgrp_data);
++ cgroup_sk_clone(&newsk->sk_cgrp_data);
+
+ rcu_read_lock();
+ filter = rcu_dereference(sk->sk_filter);
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2020-14356/0002-cgroup-Fix-sock_cgroup_data-on-big-endian.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2020-14356/0002-cgroup-Fix-sock_cgroup_data-on-big-endian.patch
new file mode 100644
index 000000000..e43c6489e
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2020-14356/0002-cgroup-Fix-sock_cgroup_data-on-big-endian.patch
@@ -0,0 +1,39 @@
+From 14b032b8f8fce03a546dcf365454bec8c4a58d7d Mon Sep 17 00:00:00 2001
+From: Cong Wang <xiyou.wangcong@gmail.com>
+Date: Thu, 9 Jul 2020 16:28:44 -0700
+Subject: [PATCH] cgroup: Fix sock_cgroup_data on big-endian.
+
+In order for no_refcnt and is_data to be the lowest order two
+bits in the 'val' we have to pad out the bitfield of the u8.
+
+Fixes: ad0f75e5f57c ("cgroup: fix cgroup_sk_alloc() for sk_clone_lock()")
+Reported-by: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+---
+ include/linux/cgroup-defs.h | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/include/linux/cgroup-defs.h b/include/linux/cgroup-defs.h
+index 4f1cd0edc57d..fee0b5547cd0 100644
+--- a/include/linux/cgroup-defs.h
++++ b/include/linux/cgroup-defs.h
+@@ -792,6 +792,7 @@ struct sock_cgroup_data {
+ struct {
+ u8 is_data : 1;
+ u8 no_refcnt : 1;
++ u8 unused : 6;
+ u8 padding;
+ u16 prioidx;
+ u32 classid;
+@@ -801,6 +802,7 @@ struct sock_cgroup_data {
+ u32 classid;
+ u16 prioidx;
+ u8 padding;
++ u8 unused : 6;
+ u8 no_refcnt : 1;
+ u8 is_data : 1;
+ } __packed;
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2020-16166/0001-random32-update-the-net-random-state-on-interrupt-an.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2020-16166/0001-random32-update-the-net-random-state-on-interrupt-an.patch
new file mode 100644
index 000000000..75633ae53
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2020-16166/0001-random32-update-the-net-random-state-on-interrupt-an.patch
@@ -0,0 +1,116 @@
+From b99b4c8e75333bec61fd0a6683d1d856b2bb0c56 Mon Sep 17 00:00:00 2001
+From: Willy Tarreau <w@1wt.eu>
+Date: Fri, 10 Jul 2020 15:23:19 +0200
+Subject: [PATCH] random32: update the net random state on interrupt and
+ activity
+
+This modifies the first 32 bits out of the 128 bits of a random CPU's
+net_rand_state on interrupt or CPU activity to complicate remote
+observations that could lead to guessing the network RNG's internal
+state.
+
+Note that depending on some network devices' interrupt rate moderation
+or binding, this re-seeding might happen on every packet or even almost
+never.
+
+In addition, with NOHZ some CPUs might not even get timer interrupts,
+leaving their local state rarely updated, while they are running
+networked processes making use of the random state. For this reason, we
+also perform this update in update_process_times() in order to at least
+update the state when there is user or system activity, since it's the
+only case we care about.
+
+Reported-by: Amit Klein <aksecurity@gmail.com>
+Suggested-by: Linus Torvalds <torvalds@linux-foundation.org>
+Cc: Eric Dumazet <edumazet@google.com>
+Cc: "Jason A. Donenfeld" <Jason@zx2c4.com>
+Cc: Andy Lutomirski <luto@kernel.org>
+Cc: Kees Cook <keescook@chromium.org>
+Cc: Thomas Gleixner <tglx@linutronix.de>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Willy Tarreau <w@1wt.eu>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+---
+ drivers/char/random.c | 1 +
+ include/linux/random.h | 3 +++
+ kernel/time/timer.c | 8 ++++++++
+ lib/random32.c | 2 +-
+ 4 files changed, 13 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/char/random.c b/drivers/char/random.c
+index 8ff28c14af7e..e877c20e0ee0 100644
+--- a/drivers/char/random.c
++++ b/drivers/char/random.c
+@@ -1330,6 +1330,7 @@ void add_interrupt_randomness(int irq, int irq_flags)
+
+ fast_mix(fast_pool);
+ add_interrupt_bench(cycles);
++ this_cpu_add(net_rand_state.s1, fast_pool->pool[cycles & 3]);
+
+ if (unlikely(crng_init == 0)) {
+ if ((fast_pool->count >= 64) &&
+diff --git a/include/linux/random.h b/include/linux/random.h
+index f189c927fdea..4d080e5ef6eb 100644
+--- a/include/linux/random.h
++++ b/include/linux/random.h
+@@ -9,6 +9,7 @@
+
+ #include <linux/list.h>
+ #include <linux/once.h>
++#include <linux/percpu.h>
+
+ #include <uapi/linux/random.h>
+
+@@ -117,6 +118,8 @@ struct rnd_state {
+ __u32 s1, s2, s3, s4;
+ };
+
++DECLARE_PER_CPU(struct rnd_state, net_rand_state) __latent_entropy;
++
+ u32 prandom_u32_state(struct rnd_state *state);
+ void prandom_bytes_state(struct rnd_state *state, void *buf, size_t nbytes);
+ void prandom_seed_full_state(struct rnd_state __percpu *pcpu_state);
+diff --git a/kernel/time/timer.c b/kernel/time/timer.c
+index 4820823515e9..226da9217f26 100644
+--- a/kernel/time/timer.c
++++ b/kernel/time/timer.c
+@@ -43,6 +43,7 @@
+ #include <linux/sched/debug.h>
+ #include <linux/slab.h>
+ #include <linux/compat.h>
++#include <linux/random.h>
+
+ #include <linux/uaccess.h>
+ #include <asm/unistd.h>
+@@ -1731,6 +1732,13 @@ void update_process_times(int user_tick)
+ scheduler_tick();
+ if (IS_ENABLED(CONFIG_POSIX_TIMERS))
+ run_posix_cpu_timers();
++
++ /* The current CPU might make use of net randoms without receiving IRQs
++ * to renew them often enough. Let's update the net_rand_state from a
++ * non-constant value that's not affine to the number of calls to make
++ * sure it's updated when there's some activity (we don't care in idle).
++ */
++ this_cpu_add(net_rand_state.s1, rol32(jiffies, 24) + user_tick);
+ }
+
+ /**
+diff --git a/lib/random32.c b/lib/random32.c
+index 763b920a6206..c4d317be2997 100644
+--- a/lib/random32.c
++++ b/lib/random32.c
+@@ -48,7 +48,7 @@ static inline void prandom_state_selftest(void)
+ }
+ #endif
+
+-static DEFINE_PER_CPU(struct rnd_state, net_rand_state) __latent_entropy;
++DEFINE_PER_CPU(struct rnd_state, net_rand_state) __latent_entropy;
+
+ /**
+ * prandom_u32_state - seeded pseudo-random number generator.
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed_%.bbappend b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed_%.bbappend
index 8250ec919..9bb40fe5c 100644
--- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed_%.bbappend
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed_%.bbappend
@@ -83,10 +83,32 @@ SRC_URI += " \
file://0110-USB-gadget-fix-illegal-array-access-in-binding-with-.patch \
file://0111-Unconditionally-calculate-the-PECI-AW-FCS.patch \
file://0112-AST2600-enable-UART-routing.patch \
+ file://0113-hwmon-peci-PCS-utils.patch \
+ file://0114-hwmon-peci-cpupower-extension.patch \
+ file://0115-hwmon-peci-dimmpower-implementation.patch \
file://0116-watchdog-aspeed-fix-AST2600-support.patch \
file://0117-Copy-raw-PECI-response-to-user-space-on-timeout.patch \
file://0118-Recalculate-AW-FCS-on-WrEndPointConfig-command.patch \
"
+# CVE-2020-16166 vulnerability fix
+FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}/CVE-2020-16166:"
+SRC_URI += " \
+ file://0001-random32-update-the-net-random-state-on-interrupt-an.patch \
+ "
+
+# CVE-2019-19770 vulnerability fix
+FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}/CVE-2019-19770:"
+SRC_URI += " \
+ file://0001-blktrace-fix-debugfs-use-after-free.patch \
+ "
+
+# CVE-2020-14356 vulnerability fix
+FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}/CVE-2020-14356:"
+SRC_URI += " \
+ file://0001-cgroup-fix-cgroup_sk_alloc-for-sk_clone_lock.patch \
+ file://0002-cgroup-Fix-sock_cgroup_data-on-big-endian.patch \
+ "
+
SRC_URI += "${@bb.utils.contains('IMAGE_FSTYPES', 'intel-pfr', 'file://0005-128MB-flashmap-for-PFR.patch', '', d)}"
SRC_URI += "${@bb.utils.contains('EXTRA_IMAGE_FEATURES', 'debug-tweaks', 'file://debug.cfg', '', d)}"
diff --git a/meta-openbmc-mods/meta-common/recipes-network/network/ncsi-monitor.bb b/meta-openbmc-mods/meta-common/recipes-network/network/ncsi-monitor.bb
new file mode 100644
index 000000000..98d053219
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-network/network/ncsi-monitor.bb
@@ -0,0 +1,25 @@
+SUMMARY = "Check for host in reset to disable the NCSI iface"
+DESCRIPTION = "If the host is in reset, the NCSI NIC will not be \
+ available, so this will manually disable the NIC"
+
+FILESEXTRAPATHS_prepend := "${THISDIR}/${BPN}:"
+
+PV = "1.0"
+
+LICENSE = "Apache-2.0"
+LIC_FILES_CHKSUM = "file://${INTELBASE}/COPYING.apache-2.0;md5=34400b68072d710fecd0a2940a0d1658"
+
+SRC_URI = "\
+ file://check-for-host-in-reset \
+ file://${BPN}.service \
+ "
+
+inherit obmc-phosphor-systemd
+
+SYSTEMD_SERVICE_${PN} += "${BPN}.service"
+
+do_install() {
+ install -d ${D}${bindir}
+ install -m 0755 ${WORKDIR}/check-for-host-in-reset ${D}/${bindir}/check-for-host-in-reset
+
+}
diff --git a/meta-openbmc-mods/meta-common/recipes-network/network/ncsi-monitor/check-for-host-in-reset b/meta-openbmc-mods/meta-common/recipes-network/network/ncsi-monitor/check-for-host-in-reset
new file mode 100755
index 000000000..aa17aebf2
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-network/network/ncsi-monitor/check-for-host-in-reset
@@ -0,0 +1,65 @@
+#!/bin/sh
+
+# PFR Boot Time Detection
+#
+# The Platform Firmware Recovery system is designed to confirm the server is
+# running valid images. The server boot process is controlled with a
+# programmable device. The programmable device prevents the system, and the
+# BMC from booting until after it has confirmed the firmware images match a
+# known checksum. Two reset controls are asserted while the checksum
+# calculation is being performed. One prevents the BMC from booting, the other
+# (RSMRST_N) prevents the main processors from leaving reset.
+#
+# If the BMC FW checksum is correct the BMC is allowed to boot.
+# If the BIOS checksum fails the BIOS is not allowed to boot.
+# In this condition the BMC will boot believing the NCSI NIC is functional.
+# This will not be the case when RMSRST_N is asserted. The BIOS will not
+# configure the shared NIC. The BMC will not be able to send or receive
+# network traffic via the shared NIC. This becomes a problem depending on how
+# the NCSI channel is configured.
+#
+# When the NCSI channel is configured using DHCP the BMC is unable to
+# communicate to a DHCP server. Unable to acquire a valid IP state, the NCSI
+# NIC is left DOWN.
+# The problem that occurs is when the NIC is configured with a static
+# address. The BMC is unable to determine the configuration state of the NCSI
+# NIC, and behaves as if everything is working. The problem is the network
+# routing table will, in most cases, be left in a state that prevents traffic
+# from being sent/received from the dedicated NIC. This prevents network
+# access to the BMC, which in turn leaves the system unrecoverable.
+#
+# The purpose of this script is to check for the assertion of the RSMRST_N
+# control at BMC boot time. It will perform this test once. In the event the
+# RSMRST_N is found to be asserted, the BMC will take the NCSI NIC down. No
+# logic for detecting the deassertion will be performed. Once the new image
+# for the BIOS has been transferred, and the checksum confirmed, the BMC will
+# be reset by the programmable device. The programmable device will confirm
+# the checksums, and release both the BMC and the BIOS to boot normally.
+#
+# Flow:
+# The service will be a one-shot that waits for the network.target, as is done
+# by BMCWeb.
+# During a normal boot the RSMRST_N will not be asserted, and this script will
+# not perform an action.
+# When RSMRST_N is asserted the NCSI channel will be given a link down
+# command. This regardless of static or DHCP configuration mode.
+
+GPIOFIND=/usr/bin/gpiofind
+GPIOGET=/usr/bin/gpioget
+RSMRST="RSMRST_N"
+
+# Read the assertion state from the RSMRST_N input
+function get_rsmrst_state {
+ local __resultVal=$1
+ local gpio_state=$($GPIOGET $($GPIOFIND "$RSMRST"))
+ eval $__resultVal="'$gpio_state'"
+ return 0
+}
+
+get_rsmrst_state rsmrst_val
+
+if [ "$rsmrst_val" -eq 0 ]
+then
+ echo "RSMRST_N is asserted, take eth1 down"
+ ip link set down dev eth1
+fi
diff --git a/meta-openbmc-mods/meta-common/recipes-network/network/ncsi-monitor/ncsi-monitor.service b/meta-openbmc-mods/meta-common/recipes-network/network/ncsi-monitor/ncsi-monitor.service
new file mode 100644
index 000000000..19554c94d
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-network/network/ncsi-monitor/ncsi-monitor.service
@@ -0,0 +1,11 @@
+[Unit]
+Description=Check for host in reset
+After=multi-user.target
+
+[Service]
+Type=oneshot
+Restart=no
+ExecStart=/usr/bin/check-for-host-in-reset
+
+[Install]
+WantedBy=multi-user.target
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/beepcode-mgr/files/beepcode_mgr.cpp b/meta-openbmc-mods/meta-common/recipes-phosphor/beepcode-mgr/files/beepcode_mgr.cpp
index 2940610da..8976a4015 100644
--- a/meta-openbmc-mods/meta-common/recipes-phosphor/beepcode-mgr/files/beepcode_mgr.cpp
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/beepcode-mgr/files/beepcode_mgr.cpp
@@ -292,12 +292,6 @@ static void beep(const uint8_t& beepPriority)
return;
}
- // Log into redfish event log
- sd_journal_send("MESSAGE=BeepCode: Priority=%d", beepPriority,
- "PRIORITY=%i", LOG_INFO, "REDFISH_MESSAGE_ID=%s",
- "OpenBMC.0.1.BeepCode", "REDFISH_MESSAGE_ARGS=%d",
- beepPriority, NULL);
-
beeper.beep(beepPriority);
return;
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0005-EventService-https-client-support.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0005-EventService-https-client-support.patch
index 274dd044a..23eac280d 100644
--- a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0005-EventService-https-client-support.patch
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0005-EventService-https-client-support.patch
@@ -1,4 +1,4 @@
-From f388587781c3d874b13b50ad39e8674f0bc08049 Mon Sep 17 00:00:00 2001
+From 1f91d5708cbe30610c0c8bbc4910709b99b8f270 Mon Sep 17 00:00:00 2001
From: AppaRao Puli <apparao.puli@linux.intel.com>
Date: Mon, 25 May 2020 16:14:39 +0530
Subject: [PATCH] EventService: https client support
@@ -17,12 +17,12 @@ Tested:
Change-Id: I44c3918b39baa2eb5fddda9d635f99aa280a422a
Signed-off-by: AppaRao Puli <apparao.puli@linux.intel.com>
---
- http/http_client.hpp | 270 +++++++++++++++++--------
+ http/http_client.hpp | 325 +++++++++++++++++--------
redfish-core/include/event_service_manager.hpp | 2 +-
- 2 files changed, 186 insertions(+), 86 deletions(-)
+ 2 files changed, 226 insertions(+), 101 deletions(-)
diff --git a/http/http_client.hpp b/http/http_client.hpp
-index e6a7db1..27d2af3 100644
+index e6a7db1..6d3d702 100644
--- a/http/http_client.hpp
+++ b/http/http_client.hpp
@@ -17,6 +17,7 @@
@@ -33,19 +33,42 @@ index e6a7db1..27d2af3 100644
#include <boost/beast/version.hpp>
#include <cstdlib>
-@@ -49,7 +50,10 @@ enum class ConnState
+@@ -30,12 +31,14 @@ namespace crow
+ {
+
+ static constexpr uint8_t maxRequestQueueSize = 50;
++static constexpr unsigned int httpReadBodyLimit = 1024;
+
+ enum class ConnState
+ {
+ initialized,
+ connectInProgress,
+ connectFailed,
++ sslHandshakeInProgress,
+ connected,
+ sendInProgress,
+ sendFailed,
+@@ -49,53 +52,97 @@ enum class ConnState
class HttpClient : public std::enable_shared_from_this<HttpClient>
{
private:
-- boost::beast::tcp_stream conn;
-+ boost::asio::io_context& ioc;
+ boost::asio::ssl::context ctx{boost::asio::ssl::context::tlsv12_client};
-+ std::shared_ptr<boost::beast::ssl_stream<boost::beast::tcp_stream>> sslConn;
-+ std::shared_ptr<boost::beast::tcp_stream> conn;
+ boost::beast::tcp_stream conn;
++ std::optional<boost::beast::ssl_stream<boost::beast::tcp_stream&>> sslConn;
boost::asio::steady_timer timer;
- boost::beast::flat_buffer buffer;
+- boost::beast::flat_buffer buffer;
++ boost::beast::flat_static_buffer<httpReadBodyLimit> buffer;
++ std::optional<
++ boost::beast::http::response_parser<boost::beast::http::string_body>>
++ parser;
boost::beast::http::request<boost::beast::http::string_body> req;
-@@ -62,14 +66,37 @@ class HttpClient : public std::enable_shared_from_this<HttpClient>
+- boost::beast::http::response<boost::beast::http::string_body> res;
+ boost::asio::ip::tcp::resolver::results_type endpoint;
+- std::vector<std::pair<std::string, std::string>> headers;
++ boost::beast::http::fields fields;
+ std::queue<std::string> requestDataQueue;
+- ConnState state;
+ std::string subId;
std::string host;
std::string port;
std::string uri;
@@ -55,59 +78,28 @@ index e6a7db1..27d2af3 100644
uint32_t retryIntervalSecs;
std::string retryPolicyAction;
bool runningTimer;
++ ConnState state;
-+ inline boost::beast::tcp_stream& getConn()
-+ {
-+ if (useSsl)
-+ {
-+ return (boost::beast::get_lowest_layer(*sslConn));
-+ }
-+ else
-+ {
-+ return (*conn);
-+ }
-+ }
-+
void doConnect()
{
+- if (state == ConnState::connectInProgress)
+ if (useSsl)
+ {
-+ sslConn = std::make_shared<
-+ boost::beast::ssl_stream<boost::beast::tcp_stream>>(ioc, ctx);
-+ }
-+ else
-+ {
-+ conn = std::make_shared<boost::beast::tcp_stream>(ioc);
++ sslConn.emplace(conn, ctx);
+ }
+
- if (state == ConnState::connectInProgress)
++ if ((state == ConnState::connectInProgress) ||
++ (state == ConnState::sslHandshakeInProgress))
{
return;
-@@ -77,25 +104,53 @@ class HttpClient : public std::enable_shared_from_this<HttpClient>
+ }
state = ConnState::connectInProgress;
BMCWEB_LOG_DEBUG << "Trying to connect to: " << host << ":" << port;
- // Set a timeout on the operation
-- conn.expires_after(std::chrono::seconds(30));
-- conn.async_connect(endpoint, [self(shared_from_this())](
-- const boost::beast::error_code& ec,
-- const boost::asio::ip::tcp::resolver::
-- results_type::endpoint_type& ep) {
-- if (ec)
-- {
-- BMCWEB_LOG_ERROR << "Connect " << ep
-- << " failed: " << ec.message();
-- self->state = ConnState::connectFailed;
-- self->checkQueue();
-- return;
-- }
-- self->state = ConnState::connected;
-- BMCWEB_LOG_DEBUG << "Connected to: " << ep;
-
-- self->checkQueue();
-- });
++
+ auto respHandler =
-+ [self(shared_from_this())](const boost::beast::error_code& ec,
++ [self(shared_from_this())](const boost::beast::error_code ec,
+ const boost::asio::ip::tcp::resolver::
+ results_type::endpoint_type& ep) {
+ if (ec)
@@ -119,7 +111,7 @@ index e6a7db1..27d2af3 100644
+ return;
+ }
+ BMCWEB_LOG_DEBUG << "Connected to: " << ep;
-+ if (self->useSsl)
++ if (self->sslConn)
+ {
+ self->performHandshake();
+ }
@@ -130,57 +122,91 @@ index e6a7db1..27d2af3 100644
+ }
+ };
+
-+ getConn().expires_after(std::chrono::seconds(30));
-+ getConn().async_connect(endpoint, std::move(respHandler));
+ conn.expires_after(std::chrono::seconds(30));
+- conn.async_connect(endpoint, [self(shared_from_this())](
+- const boost::beast::error_code& ec,
+- const boost::asio::ip::tcp::resolver::
+- results_type::endpoint_type& ep) {
+- if (ec)
+- {
+- BMCWEB_LOG_ERROR << "Connect " << ep
+- << " failed: " << ec.message();
+- self->state = ConnState::connectFailed;
+- self->checkQueue();
+- return;
+- }
+- self->state = ConnState::connected;
+- BMCWEB_LOG_DEBUG << "Connected to: " << ep;
++ conn.async_connect(endpoint, std::move(respHandler));
+ }
-+
+
+- self->checkQueue();
+- });
+ void performHandshake()
+ {
++ if (state == ConnState::sslHandshakeInProgress)
++ {
++ return;
++ }
++ state = ConnState::sslHandshakeInProgress;
++
+ sslConn->async_handshake(
+ boost::asio::ssl::stream_base::client,
-+ [self(shared_from_this())](const boost::beast::error_code& ec) {
++ [self(shared_from_this())](const boost::beast::error_code ec) {
+ if (ec)
+ {
+ BMCWEB_LOG_ERROR << "SSL handshake failed: "
+ << ec.message();
-+ self->state = ConnState::connectFailed;
-+ self->doCloseAndCheckQueue();
++ self->doCloseAndCheckQueue(ConnState::connectFailed);
+ return;
+ }
+ self->state = ConnState::connected;
-+ BMCWEB_LOG_DEBUG << "SSL Handshake successfull \n";
++ BMCWEB_LOG_DEBUG << "SSL Handshake successfull";
+
+ self->checkQueue();
+ });
}
void sendMessage(const std::string& data)
-@@ -108,7 +163,10 @@ class HttpClient : public std::enable_shared_from_this<HttpClient>
-
- BMCWEB_LOG_DEBUG << __FUNCTION__ << "(): " << host << ":" << port;
+@@ -106,100 +153,167 @@ class HttpClient : public std::enable_shared_from_this<HttpClient>
+ }
+ state = ConnState::sendInProgress;
+- BMCWEB_LOG_DEBUG << __FUNCTION__ << "(): " << host << ":" << port;
+-
- req.version(static_cast<int>(11)); // HTTP 1.1
+- req.target(uri);
+- req.method(boost::beast::http::verb::post);
++ BMCWEB_LOG_DEBUG << host << ":" << port;
+
+- // Set headers
+- for (const auto& [key, value] : headers)
+ req = {};
-+ res = {};
++ for (const auto& field : fields)
+ {
+- req.set(key, value);
++ req.set(field.name_string(), field.value());
+ }
+ req.set(boost::beast::http::field::host, host);
++ req.set(boost::beast::http::field::content_type, "text/plain");
+
-+ req.version(11); // HTTP 1.1
- req.target(uri);
- req.method(boost::beast::http::verb::post);
++ req.version(static_cast<int>(11)); // HTTP 1.1
++ req.target(uri);
++ req.method(boost::beast::http::verb::post);
+ req.keep_alive(true);
-@@ -123,83 +181,121 @@ class HttpClient : public std::enable_shared_from_this<HttpClient>
req.body() = data;
req.prepare_payload();
- // Set a timeout on the operation
- conn.expires_after(std::chrono::seconds(30));
+ auto respHandler = [self(shared_from_this())](
-+ const boost::beast::error_code& ec,
++ const boost::beast::error_code ec,
+ const std::size_t& bytesTransferred) {
+ if (ec)
+ {
+ BMCWEB_LOG_ERROR << "sendMessage() failed: " << ec.message();
-+ self->state = ConnState::sendFailed;
-+ self->doCloseAndCheckQueue();
++ self->doCloseAndCheckQueue(ConnState::sendFailed);
+ return;
+ }
+ BMCWEB_LOG_DEBUG << "sendMessage() bytes transferred: "
@@ -208,15 +234,15 @@ index e6a7db1..27d2af3 100644
- self->recvMessage();
- });
-+ getConn().expires_after(std::chrono::seconds(30));
-+ if (useSsl)
++ conn.expires_after(std::chrono::seconds(30));
++ if (sslConn)
+ {
+ boost::beast::http::async_write(*sslConn, req,
+ std::move(respHandler));
+ }
+ else
+ {
-+ boost::beast::http::async_write(*conn, req, std::move(respHandler));
++ boost::beast::http::async_write(conn, req, std::move(respHandler));
+ }
}
@@ -227,109 +253,141 @@ index e6a7db1..27d2af3 100644
- conn, buffer, res,
- [self(shared_from_this())](const boost::beast::error_code& ec,
- const std::size_t& bytesTransferred) {
-- if (ec)
-- {
-- BMCWEB_LOG_ERROR << "recvMessage() failed: "
-- << ec.message();
-- self->state = ConnState::recvFailed;
-- self->checkQueue();
-- return;
-- }
-- BMCWEB_LOG_DEBUG << "recvMessage() bytes transferred: "
-- << bytesTransferred;
-- boost::ignore_unused(bytesTransferred);
+ auto respHandler = [self(shared_from_this())](
-+ const boost::beast::error_code& ec,
++ const boost::beast::error_code ec,
+ const std::size_t& bytesTransferred) {
+ if (ec && ec != boost::beast::http::error::partial_message)
+ {
+ BMCWEB_LOG_ERROR << "recvMessage() failed: " << ec.message();
-+ self->state = ConnState::recvFailed;
-+ self->doCloseAndCheckQueue();
++ self->doCloseAndCheckQueue(ConnState::recvFailed);
+ return;
+ }
+ BMCWEB_LOG_DEBUG << "recvMessage() bytes transferred: "
+ << bytesTransferred;
+ boost::ignore_unused(bytesTransferred);
-
-- // Discard received data. We are not interested.
-- BMCWEB_LOG_DEBUG << "recvMessage() data: " << self->res;
-+ // Discard received data. We are not interested.
-+ BMCWEB_LOG_DEBUG << "recvMessage() data: " << self->res;
-
-- // Send is successful, Lets remove data from queue
-- // check for next request data in queue.
-- self->requestDataQueue.pop();
-- self->state = ConnState::idle;
-- self->checkQueue();
-- });
++
++ // TODO: check for return status code and perform
++ // retry if fails(Ex: 40x). Take action depending on
++ // retry policy.
++ BMCWEB_LOG_DEBUG << "recvMessage() data: "
++ << self->parser->get().body();
++
+ // Send is successful, Lets remove data from queue
+ // check for next request data in queue.
+ self->requestDataQueue.pop();
-+ self->state = ConnState::idle;
+
-+ if (ec == boost::beast::http::error::partial_message)
-+ {
-+ // Least bothered about recv message. Partial
-+ // message means, already data is sent. Lets close
-+ // connection and let next request open connection
-+ // to avoid truncated stream.
-+ self->state = ConnState::closed;
-+ self->doCloseAndCheckQueue();
-+ return;
-+ }
++ // Transfer ownership of the response
++ self->parser->release();
+
-+ self->checkQueue();
++ // TODO: Implement the keep-alive connections.
++ // Most of the web servers close connection abruptly
++ // and might be reason due to which its observed that
++ // stream_truncated(Next read) or partial_message
++ // errors. So for now, closing connection and re-open
++ // for all cases.
++ self->doCloseAndCheckQueue(ConnState::closed);
+ };
+
-+ getConn().expires_after(std::chrono::seconds(30));
-+ if (useSsl)
++ parser.emplace(std::piecewise_construct, std::make_tuple());
++ parser->body_limit(httpReadBodyLimit);
++ buffer.consume(buffer.size());
++
++ conn.expires_after(std::chrono::seconds(30));
++ if (sslConn)
+ {
-+ boost::beast::http::async_read(*sslConn, buffer, res,
++ boost::beast::http::async_read(*sslConn, buffer, *parser,
+ std::move(respHandler));
+ }
+ else
+ {
-+ boost::beast::http::async_read(*conn, buffer, res,
++ boost::beast::http::async_read(conn, buffer, *parser,
+ std::move(respHandler));
+ }
- }
-
++ }
++
++ void doCloseAndCheckQueue(const ConnState setState = ConnState::closed)
++ {
++ if (sslConn)
++ {
++ conn.expires_after(std::chrono::seconds(30));
++ sslConn->async_shutdown([self = shared_from_this(),
++ setState{std::move(setState)}](
++ const boost::system::error_code ec) {
+ if (ec)
+ {
+- BMCWEB_LOG_ERROR << "recvMessage() failed: "
+- << ec.message();
+- self->state = ConnState::recvFailed;
+- self->checkQueue();
+- return;
++ // Many https server closes connection abruptly
++ // i.e witnout close_notify. More details are at
++ // https://github.com/boostorg/beast/issues/824
++ if (ec == boost::asio::ssl::error::stream_truncated)
++ {
++ BMCWEB_LOG_ERROR
++ << "doCloseAndCheckQueue(): Connection "
++ "closed by server. ";
++ }
++ else
++ {
++ BMCWEB_LOG_ERROR << "doCloseAndCheckQueue() failed: "
++ << ec.message();
++ }
+ }
+- BMCWEB_LOG_DEBUG << "recvMessage() bytes transferred: "
+- << bytesTransferred;
+- boost::ignore_unused(bytesTransferred);
+-
+- // Discard received data. We are not interested.
+- BMCWEB_LOG_DEBUG << "recvMessage() data: " << self->res;
+-
+- // Send is successful, Lets remove data from queue
+- // check for next request data in queue.
+- self->requestDataQueue.pop();
+- self->state = ConnState::idle;
++ else
++ {
++ BMCWEB_LOG_DEBUG << "Connection closed gracefully...";
++ }
++ self->conn.cancel();
++ self->state = setState;
+ self->checkQueue();
+ });
+- }
+-
- void doClose()
-+ void doCloseAndCheckQueue()
- {
- boost::beast::error_code ec;
+- {
+- boost::beast::error_code ec;
- conn.socket().shutdown(boost::asio::ip::tcp::socket::shutdown_both, ec);
-+ getConn().cancel();
-+ getConn().expires_after(std::chrono::seconds(30));
-+ getConn().socket().shutdown(boost::asio::ip::tcp::socket::shutdown_both,
-+ ec);
-
+-
- state = ConnState::closed;
- // not_connected happens sometimes so don't bother reporting it.
- if (ec && ec != boost::beast::errc::not_connected)
-+ if (ec && ec != boost::asio::error::eof)
++ }
++ else
{
- BMCWEB_LOG_ERROR << "shutdown failed: " << ec.message();
- return;
-+ // Many https server closes connection abruptly
-+ // i.e witnout close_notify. More details are at
-+ // https://github.com/boostorg/beast/issues/824
-+ if (ec == boost::asio::ssl::error::stream_truncated)
++ boost::beast::error_code ec;
++ conn.expires_after(std::chrono::seconds(30));
++ conn.socket().shutdown(boost::asio::ip::tcp::socket::shutdown_both,
++ ec);
++ if (ec)
+ {
-+ BMCWEB_LOG_DEBUG
-+ << "doCloseAndCheckQueue(): Connection closed by server.";
++ BMCWEB_LOG_ERROR << "doCloseAndCheckQueue() failed: "
++ << ec.message();
+ }
+ else
+ {
-+ BMCWEB_LOG_ERROR << "doCloseAndCheckQueue() failed: "
-+ << ec.message();
++ BMCWEB_LOG_DEBUG << "Connection closed gracefully...";
+ }
- }
+
-+ getConn().close();
- BMCWEB_LOG_DEBUG << "Connection closed gracefully";
-+ checkQueue();
++ conn.close();
++ state = setState;
++ checkQueue();
+ }
+- BMCWEB_LOG_DEBUG << "Connection closed gracefully";
+ return;
}
@@ -344,7 +402,7 @@ index e6a7db1..27d2af3 100644
BMCWEB_LOG_DEBUG << "requestDataQueue is empty\n";
return;
}
-@@ -257,17 +353,20 @@ class HttpClient : public std::enable_shared_from_this<HttpClient>
+@@ -257,16 +371,17 @@ class HttpClient : public std::enable_shared_from_this<HttpClient>
BMCWEB_LOG_DEBUG << "Attempt retry after " << retryIntervalSecs
<< " seconds. RetryCount = " << retryCount;
timer.expires_after(std::chrono::seconds(retryIntervalSecs));
@@ -360,38 +418,66 @@ index e6a7db1..27d2af3 100644
+ });
return;
}
- else
+- else
++
++ if (state == ConnState::idle)
{
- // reset retry count.
-- retryCount = 0;
-+ if (state == ConnState::idle)
-+ {
-+ // State idle means, previous attempt is successful.
-+ retryCount = 0;
-+ }
++ // State idle means, previous attempt is successful.
+ retryCount = 0;
}
connStateCheck();
-
-@@ -310,10 +409,11 @@ class HttpClient : public std::enable_shared_from_this<HttpClient>
+@@ -279,6 +394,7 @@ class HttpClient : public std::enable_shared_from_this<HttpClient>
+ switch (state)
+ {
+ case ConnState::connectInProgress:
++ case ConnState::sslHandshakeInProgress:
+ case ConnState::sendInProgress:
+ case ConnState::suspended:
+ case ConnState::terminated:
+@@ -310,15 +426,19 @@ class HttpClient : public std::enable_shared_from_this<HttpClient>
public:
explicit HttpClient(boost::asio::io_context& ioc, const std::string& id,
const std::string& destIP, const std::string& destPort,
- const std::string& destUri) :
-- conn(ioc),
+ const std::string& destUri,
+ const bool inUseSsl = true) :
-+ ioc(ioc),
+ conn(ioc),
timer(ioc), subId(id), host(destIP), port(destPort), uri(destUri),
- retryCount(0), maxRetryAttempts(5),
+- retryPolicyAction("TerminateAfterRetries"), runningTimer(false)
+ useSsl(inUseSsl), retryCount(0), maxRetryAttempts(5),
- retryPolicyAction("TerminateAfterRetries"), runningTimer(false)
++ retryPolicyAction("TerminateAfterRetries"), runningTimer(false),
++ state(ConnState::initialized)
{
boost::asio::ip::tcp::resolver resolver(ioc);
++ // TODO: Use async_resolver. boost asio example
++ // code as is crashing with async_resolve().
++ // It needs debug.
+ endpoint = resolver.resolve(host, port);
+- state = ConnState::initialized;
+ }
+
+ void sendData(const std::string& data)
+@@ -344,7 +464,12 @@ class HttpClient : public std::enable_shared_from_this<HttpClient>
+ void setHeaders(
+ const std::vector<std::pair<std::string, std::string>>& httpHeaders)
+ {
+- headers = httpHeaders;
++ // Set headers
++ for (const auto& [key, value] : httpHeaders)
++ {
++ // TODO: Validate the header fileds before assign.
++ fields.set(key, value);
++ }
+ }
+
+ void setRetryConfig(const uint32_t retryAttempts,
diff --git a/redfish-core/include/event_service_manager.hpp b/redfish-core/include/event_service_manager.hpp
-index 6362112..3ab2605 100644
+index 9c42e06..2a02920 100644
--- a/redfish-core/include/event_service_manager.hpp
+++ b/redfish-core/include/event_service_manager.hpp
-@@ -383,7 +383,7 @@ class Subscription
+@@ -384,7 +384,7 @@ class Subscription
{
conn = std::make_shared<crow::HttpClient>(
crow::connections::systemBus->get_io_context(), id, host, port,
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0007-cpudimm-get-cpu-details-from-Redfish.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0007-cpudimm-get-cpu-details-from-Redfish.patch
new file mode 100644
index 000000000..ccf13e2af
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0007-cpudimm-get-cpu-details-from-Redfish.patch
@@ -0,0 +1,231 @@
+From 7e50451bc8d4c4e8fa5ee1b0e2af86c800ea2efc Mon Sep 17 00:00:00 2001
+From: jayaprakash Mutyala <mutyalax.jayaprakash@intel.com>
+Date: Mon, 13 Apr 2020 23:31:06 +0000
+Subject: [PATCH] cpudimm: get cpu details from Redfish
+
+Modified the code to fetch cpu details from Redfish
+
+Note: This patch will be removed after code is up streamed.
+https://gerrit.openbmc-project.xyz/#/c/openbmc/bmcweb/+/31294/
+
+Tested:
+1. Verified redfish validator passed
+2. Get cpu details from Redfish
+GET: https://<BMC-IP>/redfish/v1/Systems/system/Processors/cpu0
+Response:
+{
+ "@odata.id": "/redfish/v1/Systems/system/Processors/cpu0",
+ "@odata.type": "#Processor.v1_7_0.Processor",
+ "Id": "cpu0",
+ "InstructionSet": "x86-64",
+ "Manufacturer": "Intel(R) Corporation",
+ "MaxSpeedMHz": 4000,
+ "Model": "",
+ "Name": "Central Processor",
+ "ProcessorArchitecture": "x86",
+ "ProcessorId": {
+ "EffectiveFamily": "Intel Xeon processor",
+ "VendorId": "329300"
+ },
+ "ProcessorType": "CPU",
+ "SerialNumber": "",
+ "Socket": "CPU0",
+ "Status": {
+ "Health": "OK",
+ "HealthRollup": "OK",
+ "State": "Enabled"
+ },
+ "TotalCores": 18,
+ "TotalThreads": 36,
+ "Version": "Intel(R) Xeon(R) Gold 6139 CPU @ 2.30GHz"
+}
+
+GET: https://<BMC-IP>/redfish/v1/Systems/system/Processors/cpu1
+Response:
+{
+ "@odata.id": "/redfish/v1/Systems/system/Processors/cpu1",
+ "@odata.type": "#Processor.v1_7_0.Processor",
+ "Id": "cpu1",
+ "Name": "Processor",
+ "ProcessorType": "CPU",
+ "Status": {
+ "Health": "OK",
+ "HealthRollup": "OK",
+ "State": "Absent"
+ }
+}
+
+Signed-off-by: jayaprakash Mutyala <mutyalax.jayaprakash@intel.com>
+Change-Id: Idcad6e643684f4912f24c259b075a443e1da5007
+---
+ redfish-core/lib/cpudimm.hpp | 81 ++++++++++++++++++++----------------
+ 1 file changed, 46 insertions(+), 35 deletions(-)
+
+diff --git a/redfish-core/lib/cpudimm.hpp b/redfish-core/lib/cpudimm.hpp
+index ed5e641..e332a11 100644
+--- a/redfish-core/lib/cpudimm.hpp
++++ b/redfish-core/lib/cpudimm.hpp
+@@ -73,8 +73,13 @@ void getCpuDataByInterface(std::shared_ptr<AsyncResp> aResp,
+ {
+ BMCWEB_LOG_DEBUG << "Get CPU resources by interface.";
+
+- const bool* present = nullptr;
+- const bool* functional = nullptr;
++ // Added for future purpose. Once present and functional attributes added
++ // in busctl call, need to add actual logic to fetch original values.
++ bool present = false;
++ const bool functional = true;
++ auto health = std::make_shared<HealthPopulate>(aResp);
++ health->populate();
++
+ for (const auto& interface : cpuInterfacesProperties)
+ {
+ for (const auto& property : interface.second)
+@@ -93,10 +98,13 @@ void getCpuDataByInterface(std::shared_ptr<AsyncResp> aResp,
+ {
+ // Slot is not populated, set status end return
+ aResp->res.jsonValue["Status"]["State"] = "Absent";
+- aResp->res.jsonValue["Status"]["Health"] = "OK";
+ // HTTP Code will be set up automatically, just return
+ return;
+ }
++ else
++ {
++ aResp->res.jsonValue["Status"]["State"] = "Enabled";
++ }
+
+ aResp->res.jsonValue["TotalCores"] = *coresCount;
+ }
+@@ -104,7 +112,7 @@ void getCpuDataByInterface(std::shared_ptr<AsyncResp> aResp,
+ {
+ aResp->res.jsonValue["Name"] = property.second;
+ }
+- else if (property.first == "Manufacturer")
++ else if (property.first == "ProcessorManufacturer")
+ {
+ const std::string* value =
+ std::get_if<std::string>(&property.second);
+@@ -128,50 +136,48 @@ void getCpuDataByInterface(std::shared_ptr<AsyncResp> aResp,
+ {
+ aResp->res.jsonValue["MaxSpeedMHz"] = property.second;
+ }
+- else if (property.first == "ProcessorThreadCount")
+- {
+- aResp->res.jsonValue["TotalThreads"] = property.second;
+- }
+- else if (property.first == "Model")
++ else if (property.first == "ProcessorSocket")
+ {
+ const std::string* value =
+ std::get_if<std::string>(&property.second);
+ if (value != nullptr)
+ {
+- aResp->res.jsonValue["Model"] = *value;
++ aResp->res.jsonValue["Socket"] = *value;
+ }
+ }
+- else if (property.first == "PartNumber")
++ else if (property.first == "ProcessorThreadCount")
+ {
+- aResp->res.jsonValue["PartNumber"] = property.second;
++ aResp->res.jsonValue["TotalThreads"] = property.second;
+ }
+- else if (property.first == "SerialNumber")
++ else if (property.first == "ProcessorFamily")
+ {
+- aResp->res.jsonValue["SerialNumber"] = property.second;
++ const std::string* value =
++ std::get_if<std::string>(&property.second);
++ if (value != nullptr)
++ {
++ aResp->res.jsonValue["ProcessorId"]["EffectiveFamily"] =
++ *value;
++ }
+ }
+- else if (property.first == "Version")
++ else if (property.first == "ProcessorVersion")
+ {
+ aResp->res.jsonValue["Version"] = property.second;
+ }
+- else if (property.first == "Present")
+- {
+- present = std::get_if<bool>(&property.second);
+- }
+- else if (property.first == "Functional")
++ else if (property.first == "ProcessorId")
+ {
+- functional = std::get_if<bool>(&property.second);
++ const uint32_t* value = std::get_if<uint32_t>(&property.second);
++
++ if (value != nullptr && *value != 0)
++ {
++ present = true;
++ aResp->res.jsonValue["ProcessorId"]["VendorId"] =
++ boost::lexical_cast<std::string>(*value);
++ }
+ }
+ }
+ }
+
+- if ((present == nullptr) || (functional == nullptr))
+- {
+- // Important property not in desired type
+- messages::internalError(aResp->res);
+- return;
+- }
+-
+- if (*present == false)
++ if (present == false)
+ {
+ aResp->res.jsonValue["Status"]["State"] = "Absent";
+ aResp->res.jsonValue["Status"]["Health"] = "OK";
+@@ -179,7 +185,7 @@ void getCpuDataByInterface(std::shared_ptr<AsyncResp> aResp,
+ else
+ {
+ aResp->res.jsonValue["Status"]["State"] = "Enabled";
+- if (*functional == true)
++ if (functional)
+ {
+ aResp->res.jsonValue["Status"]["Health"] = "OK";
+ }
+@@ -212,6 +218,7 @@ void getCpuDataByService(std::shared_ptr<AsyncResp> aResp,
+ aResp->res.jsonValue["Name"] = "Processor";
+ aResp->res.jsonValue["ProcessorType"] = "CPU";
+
++ bool slotPresent = false;
+ std::string corePath = objPath + "/core";
+ size_t totalCores = 0;
+ for (const auto& object : dbusData)
+@@ -237,6 +244,7 @@ void getCpuDataByService(std::shared_ptr<AsyncResp> aResp,
+ {
+ if (*present == true)
+ {
++ slotPresent = true;
+ totalCores++;
+ }
+ }
+@@ -249,13 +257,16 @@ void getCpuDataByService(std::shared_ptr<AsyncResp> aResp,
+ // In getCpuDataByInterface(), state and health are set
+ // based on the present and functional status. If core
+ // count is zero, then it has a higher precedence.
+- if (totalCores == 0)
++ if (slotPresent)
+ {
+- // Slot is not populated, set status end return
+- aResp->res.jsonValue["Status"]["State"] = "Absent";
+- aResp->res.jsonValue["Status"]["Health"] = "OK";
++ if (totalCores == 0)
++ {
++ // Slot is not populated, set status end return
++ aResp->res.jsonValue["Status"]["State"] = "Absent";
++ aResp->res.jsonValue["Status"]["Health"] = "OK";
++ }
++ aResp->res.jsonValue["TotalCores"] = totalCores;
+ }
+- aResp->res.jsonValue["TotalCores"] = totalCores;
+ return;
+ },
+ service, "/xyz/openbmc_project/inventory",
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0008-systems-Fix-for-Processor-Summary-Model.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0008-systems-Fix-for-Processor-Summary-Model.patch
new file mode 100644
index 000000000..d210e3808
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0008-systems-Fix-for-Processor-Summary-Model.patch
@@ -0,0 +1,138 @@
+From ea3f3da3b29c7ecca34c12f94ce1e0364cbf9d7c Mon Sep 17 00:00:00 2001
+From: jayaprakash Mutyala <mutyalax.jayaprakash@intel.com>
+Date: Fri, 29 May 2020 00:50:46 +0000
+Subject: [PATCH] systems: Fix for Processor Summary Model
+
+Issue: Processor summary is not showing model name as expected from
+ Redfish
+
+Fix: Add condition to fetch valid model name in processor summary
+
+Tested:
+1. Verified redfish validator passed
+2. Get system details from Redfish
+GET: https://<BMC-IP>/redfish/v1/Systems/system/
+Before fix:
+Response:
+ "ProcessorSummary": {
+ "Count": 2,
+ "Model": "Unknown Processor Family",
+ "Status": {
+ "Health": "OK",
+ "HealthRollup": "OK",
+ "State": "Enabled"
+ }
+ },
+
+After fix:
+Response:
+ "ProcessorSummary": {
+ "Count": 1,
+ "Model": "Intel Xeon processor",
+ "Status": {
+ "Health": "OK",
+ "HealthRollup": "OK",
+ "State": "Enabled"
+ }
+ },
+
+Signed-off-by: jayaprakash Mutyala <mutyalax.jayaprakash@intel.com>
+Change-Id: I4af7132135aef26556839fabada623728b52be8b
+---
+ redfish-core/lib/systems.hpp | 73 +++++++++++++++++++++++-------------
+ 1 file changed, 46 insertions(+), 27 deletions(-)
+
+diff --git a/redfish-core/lib/systems.hpp b/redfish-core/lib/systems.hpp
+index 2baeaa7..884fbb6 100644
+--- a/redfish-core/lib/systems.hpp
++++ b/redfish-core/lib/systems.hpp
+@@ -325,40 +325,59 @@ void getComputerSystem(std::shared_ptr<AsyncResp> aResp,
+
+ if (properties.size() > 0)
+ {
++ const uint32_t* processorId = nullptr;
++ const std::string* procFamily = nullptr;
++ nlohmann::json& procSummary =
++ aResp->res.jsonValue["ProcessorSumm"
++ "ary"];
++ nlohmann::json& procCount =
++ procSummary["Count"];
++
++ auto procCountPtr = procCount.get_ptr<
++ nlohmann::json::
++ number_integer_t*>();
++ if (procCountPtr == nullptr)
++ {
++ messages::internalError(aResp->res);
++ return;
++ }
+ for (const auto& property : properties)
+ {
++
++ if (property.first == "ProcessorId")
++ {
++ processorId =
++ std::get_if<uint32_t>(
++ &property.second);
++ if (nullptr != procFamily)
++ break;
++ continue;
++ }
++
+ if (property.first ==
+ "ProcessorFamily")
+ {
+- const std::string* value =
++ procFamily =
+ std::get_if<std::string>(
+ &property.second);
+- if (value != nullptr)
+- {
+- nlohmann::json&
+- procSummary =
+- aResp->res.jsonValue
+- ["ProcessorSumm"
+- "ary"];
+- nlohmann::json& procCount =
+- procSummary["Count"];
+-
+- auto procCountPtr =
+- procCount.get_ptr<
+- nlohmann::json::
+- number_integer_t*>();
+- if (procCountPtr != nullptr)
+- {
+- // shouldn't be possible
+- // to be nullptr
+- *procCountPtr += 1;
+- }
+- procSummary["Status"]
+- ["State"] =
+- "Enabled";
+- procSummary["Model"] =
+- *value;
+- }
++ if (nullptr != processorId)
++ break;
++ continue;
++ }
++ }
++
++ if (procFamily != nullptr &&
++ processorId != nullptr)
++ {
++ if (procCountPtr != nullptr &&
++ *processorId != 0)
++ {
++ *procCountPtr += 1;
++ procSummary["Status"]["State"] =
++ "Enabled";
++
++ procSummary["Model"] =
++ *procFamily;
+ }
+ }
+ }
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0009-Fix-MetricReportDefinitions-filter-not-working.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0009-Fix-MetricReportDefinitions-filter-not-working.patch
new file mode 100644
index 000000000..64b3c1112
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0009-Fix-MetricReportDefinitions-filter-not-working.patch
@@ -0,0 +1,112 @@
+From 455b1d4c687a5c14197af1c1aba80b579c75900e Mon Sep 17 00:00:00 2001
+From: AppaRao Puli <apparao.puli@linux.intel.com>
+Date: Mon, 3 Aug 2020 22:23:12 +0530
+Subject: [PATCH 1/2] Fix: MetricReportDefinitions filter not working
+
+The metric reports are not sending when user configures
+the MetricReportDefinitions filter. This is of odata json
+object type. Corrected code to properly handle odata type
+object and store it as string array to make filters faster.
+
+Tested:
+ - Created metric report EventService subscription type
+ with MetricReportDefinitions and events properly sent to
+ Event listener.
+
+Signed-off-by: AppaRao Puli <apparao.puli@linux.intel.com>
+Change-Id: If96564219da7d38a2ee5e415b89824ba25cd686d
+---
+ redfish-core/include/event_service_manager.hpp | 4 ++--
+ redfish-core/lib/event_service.hpp | 32 +++++++++++++++++++++-----
+ 2 files changed, 28 insertions(+), 8 deletions(-)
+
+diff --git a/redfish-core/include/event_service_manager.hpp b/redfish-core/include/event_service_manager.hpp
+index 214f1e4..7c47842 100644
+--- a/redfish-core/include/event_service_manager.hpp
++++ b/redfish-core/include/event_service_manager.hpp
+@@ -283,7 +283,7 @@ bool isFilterQuerySpecialChar(char c)
+ bool readSSEQueryParams(std::string sseFilter, std::string& formatType,
+ std::vector<std::string>& messageIds,
+ std::vector<std::string>& registryPrefixes,
+- std::vector<nlohmann::json>& metricReportDefinitions)
++ std::vector<std::string>& metricReportDefinitions)
+ {
+ sseFilter.erase(std::remove_if(sseFilter.begin(), sseFilter.end(),
+ isFilterQuerySpecialChar),
+@@ -369,7 +369,7 @@ class Subscription
+ std::vector<std::string> registryMsgIds;
+ std::vector<std::string> registryPrefixes;
+ std::vector<nlohmann::json> httpHeaders; // key-value pair
+- std::vector<nlohmann::json> metricReportDefinitions;
++ std::vector<std::string> metricReportDefinitions;
+
+ Subscription(const Subscription&) = delete;
+ Subscription& operator=(const Subscription&) = delete;
+diff --git a/redfish-core/lib/event_service.hpp b/redfish-core/lib/event_service.hpp
+index 8bd30f5..f59d093 100644
+--- a/redfish-core/lib/event_service.hpp
++++ b/redfish-core/lib/event_service.hpp
+@@ -229,7 +229,7 @@ class EventDestinationCollection : public Node
+ std::optional<std::vector<std::string>> msgIds;
+ std::optional<std::vector<std::string>> regPrefixes;
+ std::optional<std::vector<nlohmann::json>> headers;
+- std::optional<std::vector<nlohmann::json>> metricReportDefinitions;
++ std::optional<std::vector<nlohmann::json>> mrdJsonArray;
+
+ if (!json_util::readJson(
+ req, res, "Destination", destUrl, "Context", context,
+@@ -237,7 +237,7 @@ class EventDestinationCollection : public Node
+ "EventFormatType", eventFormatType, "HttpHeaders", headers,
+ "RegistryPrefixes", regPrefixes, "MessageIds", msgIds,
+ "DeliveryRetryPolicy", retryPolicy, "MetricReportDefinitions",
+- metricReportDefinitions))
++ mrdJsonArray))
+ {
+ return;
+ }
+@@ -387,9 +387,24 @@ class EventDestinationCollection : public Node
+ subValue->retryPolicy = "TerminateAfterRetries";
+ }
+
+- if (metricReportDefinitions)
++ if (mrdJsonArray)
+ {
+- subValue->metricReportDefinitions = *metricReportDefinitions;
++ for (nlohmann::json& mrdObj : *mrdJsonArray)
++ {
++ std::string mrdUri;
++ if (json_util::getValueFromJsonObject(mrdObj, "@odata.id",
++ mrdUri))
++ {
++ subValue->metricReportDefinitions.emplace_back(mrdUri);
++ }
++ else
++ {
++ messages::propertyValueFormatError(
++ asyncResp->res, mrdObj.dump(),
++ "MetricReportDefinitions");
++ return;
++ }
++ }
+ }
+
+ std::string id =
+@@ -565,8 +580,13 @@ class EventDestination : public Node
+ subValue->registryPrefixes;
+ asyncResp->res.jsonValue["MessageIds"] = subValue->registryMsgIds;
+ asyncResp->res.jsonValue["DeliveryRetryPolicy"] = subValue->retryPolicy;
+- asyncResp->res.jsonValue["MetricReportDefinitions"] =
+- subValue->metricReportDefinitions;
++
++ std::vector<nlohmann::json> mrdJsonArray;
++ for (const auto& mdrUri : subValue->metricReportDefinitions)
++ {
++ mrdJsonArray.push_back({{"@odata.id", mdrUri}});
++ }
++ asyncResp->res.jsonValue["MetricReportDefinitions"] = mrdJsonArray;
+ }
+
+ void doPatch(crow::Response& res, const crow::Request& req,
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0009-Workaround-Fix-memory-leak.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0009-Workaround-Fix-memory-leak.patch
new file mode 100644
index 000000000..90905762b
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0009-Workaround-Fix-memory-leak.patch
@@ -0,0 +1,33 @@
+From f43d6ba7e32565a7881949070bd25cb13f50ebf7 Mon Sep 17 00:00:00 2001
+From: James Feist <james.feist@linux.intel.com>
+Date: Thu, 27 Aug 2020 13:56:52 -0700
+Subject: [PATCH 1/1] Workaround: Fix memory leak
+
+Req caputures self not allowing the connection to
+be freed. There is discussion in upstream about a
+real fix, this should be kept downstream only.
+
+Tested: Sent 1000 connections, saw no VSZ increase
+
+Change-Id: I63440abbe0882ffe228395b5d3bc869f10048ddc
+Signed-off-by: James Feist <james.feist@linux.intel.com>
+---
+ http/http_connection.h | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/http/http_connection.h b/http/http_connection.h
+index 109a272..393c2e7 100644
+--- a/http/http_connection.h
++++ b/http/http_connection.h
+@@ -422,6 +422,8 @@ class Connection :
+ {
+ adaptor.close();
+ }
++ // HACK TO REMOVE MEMORY LEAK
++ req.reset();
+ }
+
+ void completeRequest()
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0010-Fix-EventService-stops-sending-events.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0010-Fix-EventService-stops-sending-events.patch
new file mode 100644
index 000000000..d7df52ddf
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0010-Fix-EventService-stops-sending-events.patch
@@ -0,0 +1,67 @@
+From 27705854ade6832bc1e91dada33fee43ee4b2bc9 Mon Sep 17 00:00:00 2001
+From: AppaRao Puli <apparao.puli@linux.intel.com>
+Date: Sun, 2 Aug 2020 17:03:10 +0530
+Subject: [PATCH 2/2] Fix: EventService stops sending events
+
+When redfish log file(/var/log/redfish) is recreated
+by rsyslog daemon, EventService stops sending events
+to subscribers.
+
+The rsyslog service take redfish log files to back up
+as per design. EventService has inotify on redfish log
+file modifications. It needs to be removed from inotify
+watcher list and added with new File descriptor.
+Corrected code to handle remove & add of new descriptor.
+Also corrected code to properly handle last event timestamp.
+
+Tested:
+ - Ran stress test on redfish log file to create multiple
+ backup files and events sends to clients properly, in
+ all switching scenarios.
+
+Change-Id: Ic0378edfc2cae86d1f69f6df4c429d07c2744bdf
+Signed-off-by: AppaRao Puli <apparao.puli@linux.intel.com>
+---
+ redfish-core/include/event_service_manager.hpp | 12 ++++++++----
+ 1 file changed, 8 insertions(+), 4 deletions(-)
+
+diff --git a/redfish-core/include/event_service_manager.hpp b/redfish-core/include/event_service_manager.hpp
+index 7c47842..4671995 100644
+--- a/redfish-core/include/event_service_manager.hpp
++++ b/redfish-core/include/event_service_manager.hpp
+@@ -1019,6 +1019,7 @@ class EventServiceManager
+ #ifndef BMCWEB_ENABLE_REDFISH_DBUS_LOG_ENTRIES
+ void cacheLastEventTimestamp()
+ {
++ lastEventTStr.clear();
+ std::ifstream logStream(redfishEventLogFile);
+ if (!logStream.good())
+ {
+@@ -1062,7 +1063,7 @@ class EventServiceManager
+ std::string logEntry;
+ while (std::getline(logStream, logEntry))
+ {
+- if (!startLogCollection)
++ if (!startLogCollection && !lastEventTStr.empty())
+ {
+ if (boost::starts_with(logEntry, lastEventTStr))
+ {
+@@ -1160,9 +1161,12 @@ class EventServiceManager
+ if (fileWatchDesc != -1)
+ {
+ BMCWEB_LOG_DEBUG
+- << "Redfish log file is already on "
+- "inotify_add_watch.";
+- return;
++ << "Remove and Add inotify watcher on "
++ "redfish event log file";
++ // Remove existing inotify watcher and add
++ // with new redfish event log file.
++ inotify_rm_watch(inotifyFd, fileWatchDesc);
++ fileWatchDesc = -1;
+ }
+
+ fileWatchDesc = inotify_add_watch(
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0011-Deallocate-memory-during-failed-case.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0011-Deallocate-memory-during-failed-case.patch
new file mode 100644
index 000000000..57ec01c7b
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0011-Deallocate-memory-during-failed-case.patch
@@ -0,0 +1,32 @@
+From cf5ba2028909d4fa0ee3bba4b60620e72cd612f0 Mon Sep 17 00:00:00 2001
+From: AppaRao Puli <apparao.puli@linux.intel.com>
+Date: Fri, 7 Aug 2020 01:37:28 +0530
+Subject: [PATCH] Deallocate memory during failed case
+
+Free memory during failed case inside
+pamFunctionConversation() function.
+
+Tested:
+ - Pam authentication works as normal.
+
+Signed-off-by: AppaRao Puli <apparao.puli@linux.intel.com>
+Change-Id: I81c06a3d674b0806c96e5847cda6f208795bd02c
+---
+ include/pam_authenticate.hpp | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/include/pam_authenticate.hpp b/include/pam_authenticate.hpp
+index f2c7356..3e5c691 100644
+--- a/include/pam_authenticate.hpp
++++ b/include/pam_authenticate.hpp
+@@ -30,6 +30,7 @@ inline int pamFunctionConversation(int numMsg, const struct pam_message** msg,
+
+ if (resp == nullptr)
+ {
++ free(pass);
+ return PAM_AUTH_ERR;
+ }
+
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0012-System-Replace-chassis-name-in-Redfish.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0012-System-Replace-chassis-name-in-Redfish.patch
new file mode 100644
index 000000000..870b33249
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0012-System-Replace-chassis-name-in-Redfish.patch
@@ -0,0 +1,64 @@
+From e0e19506ac81b3fa858de30c90ed3d75e10df749 Mon Sep 17 00:00:00 2001
+From: srikanta mondal <srikantax.mondal@intel.com>
+Date: Wed, 12 Aug 2020 18:26:26 +0000
+Subject: [PATCH] System: Replace chassis name in Redfish
+
+Modify code to replace chassis name to WC_Baseboard
+
+Note: This patch will be removed after code is up streamed.
+https://gerrit.openbmc-project.xyz/#/c/openbmc/bmcweb/+/31748/
+
+Tested:
+1. Verified redfish validator passed
+2. Verified details from Redfish
+
+GET: https://<BMC-IP>/redfish/v1/Systems/system
+Response:
+{
+ ....
+ "Links": {
+ "Chassis": [
+ {
+ "@odata.id": "/redfish/v1/Chassis/WC_Baseboard"
+ }
+ ],
+ "ManagedBy": [
+ {
+ "@odata.id": "/redfish/v1/Managers/bmc"
+ }
+ ]
+ },
+ ....
+}
+
+GET: https://<BMC-IP>/redfish/v1/Chassis/WC_Baseboard
+Response:
+{
+ // SUCCESS
+}
+
+Signed-off-by: James Feist <james.feist@linux.intel.com>
+Signed-off-by: srikanta mondal <srikantax.mondal@intel.com>
+---
+ redfish-core/lib/redfish_util.hpp | 5 ++---
+ 1 file changed, 2 insertions(+), 3 deletions(-)
+
+diff --git a/redfish-core/lib/redfish_util.hpp b/redfish-core/lib/redfish_util.hpp
+index 5701712..3adb392 100644
+--- a/redfish-core/lib/redfish_util.hpp
++++ b/redfish-core/lib/redfish_util.hpp
+@@ -57,9 +57,8 @@ void getMainChassisId(std::shared_ptr<AsyncResp> asyncResp,
+ "/xyz/openbmc_project/object_mapper",
+ "xyz.openbmc_project.ObjectMapper", "GetSubTree",
+ "/xyz/openbmc_project/inventory", 0,
+- std::array<const char*, 2>{
+- "xyz.openbmc_project.Inventory.Item.Board",
+- "xyz.openbmc_project.Inventory.Item.Chassis"});
++ std::array<const char*, 1>{
++ "xyz.openbmc_project.Inventory.Item.System"});
+ }
+ } // namespace redfish
+ #endif
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0013-url_view-throws-if-a-parse-error-is-found.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0013-url_view-throws-if-a-parse-error-is-found.patch
new file mode 100644
index 000000000..c7d4ca914
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0013-url_view-throws-if-a-parse-error-is-found.patch
@@ -0,0 +1,54 @@
+From 6ab885e4cabe28f74050b7e996868e4d8387e94d Mon Sep 17 00:00:00 2001
+From: Ed Tanous <ed@tanous.net>
+Date: Mon, 17 Aug 2020 15:04:58 -0700
+Subject: [PATCH] url_view throws if a parse error is found
+
+This causes a strange condition where the webserver crashes on bad urls.
+
+Tested:
+Loaded on RPI. Verified that this particular crash no longer breaks the
+fuzzer.
+
+Signed-off-by: Ed Tanous <ed@tanous.net>
+Signed-off-by: James Feist <james.feist@linux.intel.com>
+Signed-off-by: AppaRao Puli <apparao.puli@linux.intel.com>
+Change-Id: I459421e27c8d07c2bc45099b5942f7c7c929610d
+---
+ http/http_connection.h | 21 ++++++++++++++++++---
+ 1 file changed, 18 insertions(+), 3 deletions(-)
+
+diff --git a/http/http_connection.h b/http/http_connection.h
+index 8dba3d6..8db8108 100644
+--- a/http/http_connection.h
++++ b/http/http_connection.h
+@@ -728,9 +728,24 @@ class Connection :
+ return;
+ }
+
+- req->urlView = boost::urls::url_view(req->target());
+- req->url = req->urlView.encoded_path();
+-
++ // Note, despite the bmcweb coding policy on use of exceptions
++ // for error handling, this one particular use of exceptions is
++ // deemed acceptible, as it solved a significant error handling
++ // problem that resulted in seg faults, the exact thing that the
++ // exceptions rule is trying to avoid. If at some point,
++ // boost::urls makes the parser object public (or we port it
++ // into bmcweb locally) this will be replaced with
++ // parser::parse, which returns a status code
++
++ try
++ {
++ req->urlView = boost::urls::url_view(req->target());
++ req->url = req->urlView.encoded_path();
++ }
++ catch (std::exception& p)
++ {
++ BMCWEB_LOG_ERROR << p.what();
++ }
+ crow::authorization::authenticate(*req, res, session);
+
+ bool loggedIn = req && req->session;
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0014-add-sufficient-delay-to-create-fw-update-object.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0014-add-sufficient-delay-to-create-fw-update-object.patch
new file mode 100644
index 000000000..e6fd85f85
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0014-add-sufficient-delay-to-create-fw-update-object.patch
@@ -0,0 +1,44 @@
+From d7df47f5df9c6e389c3deeb418be8fb7c32bc6f4 Mon Sep 17 00:00:00 2001
+From: Chalapathi Venkataramashetty <chalapathix.venkataramashetty@intel.com>
+Date: Tue, 25 Aug 2020 15:44:35 +0000
+Subject: [PATCH] add sufficient delay to create fw update object
+
+Add support to increase timeoutTimeSeconds to 10 secs to allow firmware
+object to create successfully to proceed for firmware update.
+
+Tested:
+Redfish validator passed.
+
+Updated the firmware using redfish for 16 times continuously.
+POST: https://<BMC_IP>/redfish/v1/UpdateService/
+ with <BMC_signed_cap> binary file
+firmware updated.
+{
+ "@odata.id": "/redfish/v1/TaskService/Tasks/0",
+ "@odata.type": "#Task.v1_4_3.Task",
+ "Id": "0",
+ "TaskState": "Running",
+ "TaskStatus": "OK"
+}
+
+Signed-off-by: Chalapathi Venkataramashetty <chalapathix.venkataramashetty@intel.com>
+---
+ redfish-core/lib/update_service.hpp | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/redfish-core/lib/update_service.hpp b/redfish-core/lib/update_service.hpp
+index 9407d75..ec5ab8c 100644
+--- a/redfish-core/lib/update_service.hpp
++++ b/redfish-core/lib/update_service.hpp
+@@ -363,7 +363,7 @@ static void softwareInterfaceAdded(std::shared_ptr<AsyncResp> asyncResp,
+ static void monitorForSoftwareAvailable(
+ std::shared_ptr<AsyncResp> asyncResp, const crow::Request& req,
+ const std::string& url, const std::vector<std::string>& imgUriTargets,
+- int timeoutTimeSeconds = 5)
++ int timeoutTimeSeconds = 10)
+ {
+ // Only allow one FW update at a time
+ if (fwUpdateInProgress != false)
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0015-Add-firmware-activation-messages-to-the-registry.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0015-Add-firmware-activation-messages-to-the-registry.patch
new file mode 100644
index 000000000..6cc95eda5
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0015-Add-firmware-activation-messages-to-the-registry.patch
@@ -0,0 +1,72 @@
+From d61d668f6db81bed90f41c3a128ce6fd652cc98c Mon Sep 17 00:00:00 2001
+From: "Jason M. Bills" <jason.m.bills@linux.intel.com>
+Date: Wed, 12 Aug 2020 14:45:32 -0700
+Subject: [PATCH] Add firmware activation messages to the registry
+
+In some situations a firmware requires activation rather than
+update. These messages are intended to cover those situations.
+
+Tested:
+Logged these events and confirmed that they appear correctly in
+Redfish.
+
+Change-Id: I6171b9584626e049349a26c414146f37c04768c7
+Signed-off-by: Jason M. Bills <jason.m.bills@linux.intel.com>
+---
+ .../registries/openbmc_message_registry.hpp | 33 ++++++++++++++++++-
+ 1 file changed, 32 insertions(+), 1 deletion(-)
+
+diff --git a/redfish-core/include/registries/openbmc_message_registry.hpp b/redfish-core/include/registries/openbmc_message_registry.hpp
+index 236002e..58c085d 100644
+--- a/redfish-core/include/registries/openbmc_message_registry.hpp
++++ b/redfish-core/include/registries/openbmc_message_registry.hpp
+@@ -29,7 +29,7 @@ const Header header = {
+ "0.1.0",
+ "OpenBMC",
+ };
+-constexpr std::array<MessageEntry, 182> registry = {
++constexpr std::array<MessageEntry, 185> registry = {
+ MessageEntry{
+ "ADDDCCorrectable",
+ {
+@@ -443,6 +443,37 @@ constexpr std::array<MessageEntry, 182> registry = {
+ {"string"},
+ "None.",
+ }},
++ MessageEntry{
++ "FirmwareActivationCompleted",
++ {
++ "Indicates a firmware activation has completed successfully.",
++ "%1 firmware activation completed successfully.",
++ "OK",
++ "OK",
++ 1,
++ {"string"},
++ "None.",
++ }},
++ MessageEntry{"FirmwareActivationFailed",
++ {
++ "Indicates a firmware activation has failed.",
++ "%1 firmware activation failed: %2.",
++ "Warning",
++ "Warning",
++ 2,
++ {"string", "string"},
++ "None.",
++ }},
++ MessageEntry{"FirmwareActivationStarted",
++ {
++ "Indicates a firmware activation has started.",
++ "%1 firmware activation started.",
++ "OK",
++ "OK",
++ 1,
++ {"string"},
++ "None.",
++ }},
+ MessageEntry{"FirmwareUpdateCompleted",
+ {
+ "Indicates a firmware update has completed successfully.",
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0006-Fix-MetricReport-timestamp-for-EventService.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0016-EventService-Fix-type-mismatch-in-MetricReport.patch
index 75d49b6d6..378ce6c47 100644
--- a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0006-Fix-MetricReport-timestamp-for-EventService.patch
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0016-EventService-Fix-type-mismatch-in-MetricReport.patch
@@ -1,18 +1,23 @@
-From b71f087a173c36a16526156fa34581673e2b860c Mon Sep 17 00:00:00 2001
+From cdfc5cfad41bcfa3fc0e53023bd62bdadf15ad86 Mon Sep 17 00:00:00 2001
From: "Wludzik, Jozef" <jozef.wludzik@intel.com>
Date: Fri, 24 Jul 2020 17:05:38 +0200
-Subject: [PATCH 6/6] Fix MetricReport timestamp for EventService
+Subject: [PATCH] EventService: Fix type mismatch in MetricReport
-Changed MetricReport timestamp type from std::string to int32_t.
+Fix the type mismatch in MetricReport data which
+is sent to Event Subscribers. Change below properties
+type to match with MetricReport schema.
+ - Timestamp: It should be uint32_t type.
+ - MetricValue: It should be string type.
Signed-off-by: Wludzik, Jozef <jozef.wludzik@intel.com>
+Signed-off-by: AppaRao Puli <apparao.puli@linux.intel.com>
Change-Id: I0a52b6963e7bedda89a216256f64764cd8799bf1
---
redfish-core/include/event_service_manager.hpp | 23 +++++++++++++----------
1 file changed, 13 insertions(+), 10 deletions(-)
diff --git a/redfish-core/include/event_service_manager.hpp b/redfish-core/include/event_service_manager.hpp
-index d2f4f2a..dc04ccb 100644
+index 3e3058f..0f5c6b7 100644
--- a/redfish-core/include/event_service_manager.hpp
+++ b/redfish-core/include/event_service_manager.hpp
@@ -38,7 +38,7 @@ namespace redfish
@@ -36,12 +41,12 @@ index d2f4f2a..dc04ccb 100644
+
+ entry = {{"MetricId", id},
+ {"MetricProperty", property},
-+ {"MetricValue", value},
++ {"MetricValue", std::to_string(value)},
+ {"Timestamp", crow::utility::getDateTime(timestamp)}};
}
nlohmann::json msg = {
-@@ -1266,7 +1268,7 @@ class EventServiceManager
+@@ -1270,7 +1272,7 @@ class EventServiceManager
[idStr{std::move(idStr)}](
const boost::system::error_code ec,
boost::container::flat_map<
@@ -50,7 +55,7 @@ index d2f4f2a..dc04ccb 100644
resp) {
if (ec)
{
-@@ -1275,8 +1277,8 @@ class EventServiceManager
+@@ -1279,8 +1281,8 @@ class EventServiceManager
return;
}
@@ -61,7 +66,7 @@ index d2f4f2a..dc04ccb 100644
if (!timestampPtr)
{
BMCWEB_LOG_DEBUG << "Failed to Get timestamp.";
-@@ -1303,8 +1305,9 @@ class EventServiceManager
+@@ -1307,8 +1309,9 @@ class EventServiceManager
std::shared_ptr<Subscription> entry = it.second;
if (entry->eventFormatType == metricReportFormatType)
{
@@ -74,5 +79,5 @@ index d2f4f2a..dc04ccb 100644
}
},
--
-2.16.6
+2.7.4
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0017-Add-MutualExclusiveProperties-registry.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0017-Add-MutualExclusiveProperties-registry.patch
new file mode 100644
index 000000000..2b510e0b5
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0017-Add-MutualExclusiveProperties-registry.patch
@@ -0,0 +1,151 @@
+From 891a0a2deb616b7e3f135b5df8501947ce5d6ad4 Mon Sep 17 00:00:00 2001
+From: AppaRao Puli <apparao.puli@linux.intel.com>
+Date: Tue, 8 Sep 2020 01:53:21 +0530
+Subject: [PATCH] Add MutualExclusiveProperties registry
+
+Add MutualExclusiveProperties message registry entry
+and error message.
+As per redfish specification, "RegistryPrefixes" and
+"MessageIds" are mutually exclusive. So add check for
+same in EventService and return MutualExclusiveProperties
+error message.
+
+Tested:
+ - Create subscription failed with error(bad request)
+ when the request body contain both "RegistryPrefixes"
+ and "MessageIds".
+
+Change-Id: I4c14f946977bce2ced8a7f96eb85855117fde9a8
+Signed-off-by: AppaRao Puli <apparao.puli@linux.intel.com>
+---
+ redfish-core/include/error_messages.hpp | 14 +++++++++++
+ .../include/registries/base_message_registry.hpp | 18 +++++++++++++-
+ redfish-core/lib/event_service.hpp | 10 ++++++++
+ redfish-core/src/error_messages.cpp | 29 ++++++++++++++++++++++
+ 4 files changed, 70 insertions(+), 1 deletion(-)
+
+diff --git a/redfish-core/include/error_messages.hpp b/redfish-core/include/error_messages.hpp
+index 0243be9..9a2d1ca 100644
+--- a/redfish-core/include/error_messages.hpp
++++ b/redfish-core/include/error_messages.hpp
+@@ -787,6 +787,20 @@ nlohmann::json invalidUpload(const std::string& arg1, const std::string& arg2);
+ void invalidUpload(crow::Response& res, const std::string& arg1,
+ const std::string& arg2);
+
++/**
++ * @brief Formats MutualExclusiveProperties message into JSON
++ * Message body: "The properties <arg1> and <arg2> are mutually exclusive."
++ *
++ * @param[in] arg1 Parameter of message that will replace %1 in its body.
++ * @param[in] arg2 Parameter of message that will replace %2 in its body.
++ *
++ * @returns Message MutualExclusiveProperties formatted to JSON */
++nlohmann::json mutualExclusiveProperties(const std::string& arg1,
++ const std::string& arg2);
++
++void mutualExclusiveProperties(crow::Response& res, const std::string& arg1,
++ const std::string& arg2);
++
+ } // namespace messages
+
+ } // namespace redfish
+diff --git a/redfish-core/include/registries/base_message_registry.hpp b/redfish-core/include/registries/base_message_registry.hpp
+index 90aef56..7c385a0 100644
+--- a/redfish-core/include/registries/base_message_registry.hpp
++++ b/redfish-core/include/registries/base_message_registry.hpp
+@@ -36,7 +36,7 @@ const Header header = {
+ constexpr const char* url =
+ "https://redfish.dmtf.org/registries/Base.1.8.1.json";
+
+-constexpr std::array<MessageEntry, 73> registry = {
++constexpr std::array<MessageEntry, 74> registry = {
+ MessageEntry{
+ "AccessDenied",
+ {
+@@ -429,6 +429,22 @@ constexpr std::array<MessageEntry, 73> registry = {
+ "Resolve other reported errors and retry the current operation.",
+ }},
+ MessageEntry{
++ "MutualExclusiveProperties",
++ {
++ "Indicates that the requested operation could not be completed, "
++ "because of a conflict properties.",
++ "The properties '%1' and '%2' are mutually exclusive.",
++ "Warning",
++ "Warning",
++ 2,
++ {
++ "string",
++ "string",
++ },
++ "Ensure that the request body doesn't have mutually exclusive "
++ "properties and resubmit the request.",
++ }},
++ MessageEntry{
+ "NoOperation",
+ {
+ "Indicates that the requested operation will not perform any "
+diff --git a/redfish-core/lib/event_service.hpp b/redfish-core/lib/event_service.hpp
+index f59d093..4804d26 100644
+--- a/redfish-core/lib/event_service.hpp
++++ b/redfish-core/lib/event_service.hpp
+@@ -242,6 +242,16 @@ class EventDestinationCollection : public Node
+ return;
+ }
+
++ if (regPrefixes && msgIds)
++ {
++ if (regPrefixes->size() && msgIds->size())
++ {
++ messages::mutualExclusiveProperties(
++ asyncResp->res, "RegistryPrefixes", "MessageIds");
++ return;
++ }
++ }
++
+ // Validate the URL using regex expression
+ // Format: <protocol>://<host>:<port>/<uri>
+ // protocol: http/https
+diff --git a/redfish-core/src/error_messages.cpp b/redfish-core/src/error_messages.cpp
+index 160b73f..c6938ba 100644
+--- a/redfish-core/src/error_messages.cpp
++++ b/redfish-core/src/error_messages.cpp
+@@ -1750,6 +1750,35 @@ nlohmann::json invalidUpload(const std::string& arg1, const std::string& arg2)
+ {"Resolution", "None."}};
+ }
+
++/**
++ * @internal
++ * @brief Formats MutualExclusiveProperties into JSON
++ *
++ * See header file for more information
++ * @endinternal
++ */
++nlohmann::json mutualExclusiveProperties(const std::string& arg1,
++ const std::string& arg2)
++{
++ return nlohmann::json{
++ {"@odata.type", "#Message.v1_0_0.Message"},
++ {"MessageId", "Base.1.5.0.MutualExclusiveProperties"},
++ {"Message", "The properties " + arg1 + " and " + arg2 +
++ " are mutually exclusive."},
++ {"MessageArgs", {arg1, arg2}},
++ {"Severity", "Warning"},
++ {"Resolution",
++ "Ensure that the request body doesn't contain mutually exclusive "
++ "properties and resubmit the request."}};
++}
++
++void mutualExclusiveProperties(crow::Response& res, const std::string& arg1,
++ const std::string& arg2)
++{
++ res.result(boost::beast::http::status::bad_request);
++ addMessageToErrorJson(res.jsonValue, mutualExclusiveProperties(arg1, arg2));
++}
++
+ } // namespace messages
+
+ } // namespace redfish
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0018-Add-sse-event-sequence-number.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0018-Add-sse-event-sequence-number.patch
new file mode 100644
index 000000000..e2b8644d8
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0018-Add-sse-event-sequence-number.patch
@@ -0,0 +1,74 @@
+From c03fa3c7b6c98d299f18e106c1aabf655db10327 Mon Sep 17 00:00:00 2001
+From: AppaRao Puli <apparao.puli@linux.intel.com>
+Date: Fri, 4 Sep 2020 16:44:52 +0530
+Subject: [PATCH] Add sse event sequence number
+
+Add sequence number to sse events.
+This is different for event ID's.
+
+Tested:
+ - The sequence number increments properly
+ after sending sse events.
+
+Change-Id: I8f48082497094a0435d4a400cb8068c3af506a7a
+Signed-off-by: AppaRao Puli <apparao.puli@linux.intel.com>
+---
+ redfish-core/include/event_service_manager.hpp | 2 +-
+ redfish-core/include/server_sent_events.hpp | 7 ++++---
+ 2 files changed, 5 insertions(+), 4 deletions(-)
+
+diff --git a/redfish-core/include/event_service_manager.hpp b/redfish-core/include/event_service_manager.hpp
+index 4671995..1a99e54 100644
+--- a/redfish-core/include/event_service_manager.hpp
++++ b/redfish-core/include/event_service_manager.hpp
+@@ -415,7 +415,7 @@ class Subscription
+
+ if (sseConn != nullptr)
+ {
+- sseConn->sendData(eventSeqNum, msg);
++ sseConn->sendData(msg);
+ }
+ }
+
+diff --git a/redfish-core/include/server_sent_events.hpp b/redfish-core/include/server_sent_events.hpp
+index 1c4d2a5..23517ca 100644
+--- a/redfish-core/include/server_sent_events.hpp
++++ b/redfish-core/include/server_sent_events.hpp
+@@ -56,6 +56,7 @@ class ServerSentEvents : public std::enable_shared_from_this<ServerSentEvents>
+ SseConnState state;
+ int retryCount;
+ int maxRetryAttempts;
++ uint64_t sseEventId;
+
+ void sendEvent(const std::string& id, const std::string& msg)
+ {
+@@ -260,7 +261,7 @@ class ServerSentEvents : public std::enable_shared_from_this<ServerSentEvents>
+
+ ServerSentEvents(const std::shared_ptr<crow::Request::Adaptor>& adaptor) :
+ sseConn(std::move(adaptor)), state(SseConnState::startInit),
+- retryCount(0), maxRetryAttempts(5)
++ retryCount(0), maxRetryAttempts(5), sseEventId(1)
+ {
+ startSSE();
+ }
+@@ -268,7 +269,7 @@ class ServerSentEvents : public std::enable_shared_from_this<ServerSentEvents>
+ ~ServerSentEvents()
+ {}
+
+- void sendData(const uint64_t& id, const std::string& data)
++ void sendData(const std::string& data)
+ {
+ if (state == SseConnState::suspended)
+ {
+@@ -277,7 +278,7 @@ class ServerSentEvents : public std::enable_shared_from_this<ServerSentEvents>
+
+ if (requestDataQueue.size() <= maxReqQueueSize)
+ {
+- requestDataQueue.push(std::pair(id, data));
++ requestDataQueue.push(std::pair(sseEventId++, data));
+ checkQueue(true);
+ }
+ else
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0019-EventService-Limit-SSE-connections-as-per-design.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0019-EventService-Limit-SSE-connections-as-per-design.patch
new file mode 100644
index 000000000..c6c0634ce
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0019-EventService-Limit-SSE-connections-as-per-design.patch
@@ -0,0 +1,108 @@
+From eb1f888660bd34bde0c049e48db2404803b57d6e Mon Sep 17 00:00:00 2001
+From: AppaRao Puli <apparao.puli@linux.intel.com>
+Date: Tue, 8 Sep 2020 02:37:19 +0530
+Subject: [PATCH] EventService: Limit SSE connections as per design
+
+Limit the number of SSE connections for event service.
+
+Tested:
+ - Tried creating more than 10 SSE connections and it fails.
+
+Change-Id: I4c7aa5c05a832115717e1261e330350ce59ab630
+Signed-off-by: AppaRao Puli <apparao.puli@linux.intel.com>
+---
+ redfish-core/include/event_service_manager.hpp | 17 +++++++++++++++++
+ redfish-core/lib/event_service.hpp | 14 +++++++++-----
+ 2 files changed, 26 insertions(+), 5 deletions(-)
+
+diff --git a/redfish-core/include/event_service_manager.hpp b/redfish-core/include/event_service_manager.hpp
+index 502a6f7..22d1f10 100644
+--- a/redfish-core/include/event_service_manager.hpp
++++ b/redfish-core/include/event_service_manager.hpp
+@@ -44,6 +44,9 @@ using EventServiceConfig = std::tuple<bool, uint32_t, uint32_t>;
+ static constexpr const char* eventFormatType = "Event";
+ static constexpr const char* metricReportFormatType = "MetricReport";
+
++static constexpr const char* subscriptionTypeRedfishEvent = "RedfishEvent";
++static constexpr const char* subscriptionTypeSSE = "SSE";
++
+ static constexpr const char* eventServiceFile =
+ "/var/lib/bmcweb/eventservice_config.json";
+
+@@ -983,6 +986,20 @@ class EventServiceManager
+ return subscriptionsMap.size();
+ }
+
++ size_t getNumberOfSSESubscriptions()
++ {
++ size_t count = 0;
++ for (const auto& it : this->subscriptionsMap)
++ {
++ std::shared_ptr<Subscription> entry = it.second;
++ if (entry->subscriptionType == subscriptionTypeSSE)
++ {
++ count++;
++ }
++ }
++ return count;
++ }
++
+ std::vector<std::string> getAllIDs()
+ {
+ std::vector<std::string> idList;
+diff --git a/redfish-core/lib/event_service.hpp b/redfish-core/lib/event_service.hpp
+index 4804d26..f14c03e 100644
+--- a/redfish-core/lib/event_service.hpp
++++ b/redfish-core/lib/event_service.hpp
+@@ -27,6 +27,7 @@ static constexpr const std::array<const char*, 3> supportedRetryPolicies = {
+ "TerminateAfterRetries", "SuspendRetries", "RetryForever"};
+
+ static constexpr const uint8_t maxNoOfSubscriptions = 20;
++static constexpr const uint8_t maxNoOfSSESubscriptions = 10;
+
+ class EventService : public Node
+ {
+@@ -307,7 +308,7 @@ class EventDestinationCollection : public Node
+
+ if (subscriptionType)
+ {
+- if (*subscriptionType != "RedfishEvent")
++ if (*subscriptionType != subscriptionTypeRedfishEvent)
+ {
+ messages::propertyValueNotInList(
+ asyncResp->res, *subscriptionType, "SubscriptionType");
+@@ -317,7 +318,8 @@ class EventDestinationCollection : public Node
+ }
+ else
+ {
+- subValue->subscriptionType = "RedfishEvent"; // Default
++ subValue->subscriptionType =
++ subscriptionTypeRedfishEvent; // Default
+ }
+
+ if (protocol != "Redfish")
+@@ -450,8 +452,10 @@ class EventServiceSSE : public Node
+ void doGet(crow::Response& res, const crow::Request& req,
+ const std::vector<std::string>& params) override
+ {
+- if (EventServiceManager::getInstance().getNumberOfSubscriptions() >=
+- maxNoOfSubscriptions)
++ if ((EventServiceManager::getInstance().getNumberOfSubscriptions() >=
++ maxNoOfSubscriptions) ||
++ EventServiceManager::getInstance().getNumberOfSSESubscriptions() >=
++ maxNoOfSSESubscriptions)
+ {
+ messages::eventSubscriptionLimitExceeded(res);
+ res.end();
+@@ -464,7 +468,7 @@ class EventServiceSSE : public Node
+ std::make_shared<Subscription>(sseConn);
+
+ // GET on this URI means, Its SSE subscriptionType.
+- subValue->subscriptionType = "SSE";
++ subValue->subscriptionType = subscriptionTypeSSE;
+
+ // Default values
+ subValue->protocol = "Redfish";
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0020-EventService-Validate-SSE-query-filters.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0020-EventService-Validate-SSE-query-filters.patch
new file mode 100644
index 000000000..8f3e1fc9b
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0020-EventService-Validate-SSE-query-filters.patch
@@ -0,0 +1,262 @@
+From 5fd71f098aad2f6d64e94343738c43ffdff5709e Mon Sep 17 00:00:00 2001
+From: AppaRao Puli <apparao.puli@linux.intel.com>
+Date: Tue, 8 Sep 2020 16:19:30 +0530
+Subject: [PATCH] EventService: Validate SSE query filters
+
+Validate the query filters which are specified in
+requested url and return with error if not supported.
+Also RegistryPrefix and MessageId are mutually exclusive
+as per redfish specification. so return error if user
+specifies both.
+
+Tested:
+ - Checked with invalid query filters and it returns
+ the error.
+
+Change-Id: If07341f39d8c6b9bc229baae966f8569ebdd7b19
+Signed-off-by: AppaRao Puli <apparao.puli@linux.intel.com>
+---
+ redfish-core/include/error_messages.hpp | 9 ++
+ .../include/registries/base_message_registry.hpp | 14 ++-
+ redfish-core/lib/event_service.hpp | 99 +++++++++++++++-------
+ redfish-core/src/error_messages.cpp | 26 ++++++
+ 4 files changed, 116 insertions(+), 32 deletions(-)
+
+diff --git a/redfish-core/include/error_messages.hpp b/redfish-core/include/error_messages.hpp
+index 9a2d1ca..fd6bb48 100644
+--- a/redfish-core/include/error_messages.hpp
++++ b/redfish-core/include/error_messages.hpp
+@@ -801,6 +801,15 @@ nlohmann::json mutualExclusiveProperties(const std::string& arg1,
+ void mutualExclusiveProperties(crow::Response& res, const std::string& arg1,
+ const std::string& arg2);
+
++/**
++ * @brief Formats InvalidQueryFilter message into JSON
++ * Message body: "The requested URL contains the invalid query filters"
++ *
++ * @returns Message InvalidQueryFilter formatted to JSON */
++nlohmann::json invalidQueryFilter();
++
++void invalidQueryFilter(crow::Response& res);
++
+ } // namespace messages
+
+ } // namespace redfish
+diff --git a/redfish-core/include/registries/base_message_registry.hpp b/redfish-core/include/registries/base_message_registry.hpp
+index 7c385a0..18085c8 100644
+--- a/redfish-core/include/registries/base_message_registry.hpp
++++ b/redfish-core/include/registries/base_message_registry.hpp
+@@ -36,7 +36,7 @@ const Header header = {
+ constexpr const char* url =
+ "https://redfish.dmtf.org/registries/Base.1.8.1.json";
+
+-constexpr std::array<MessageEntry, 74> registry = {
++constexpr std::array<MessageEntry, 75> registry = {
+ MessageEntry{
+ "AccessDenied",
+ {
+@@ -403,6 +403,18 @@ constexpr std::array<MessageEntry, 74> registry = {
+ "Either the object is malformed or the URI is not correct. "
+ "Correct the condition and resubmit the request if it failed.",
+ }},
++ MessageEntry{
++ "InvalidQueryFilter",
++ {
++ "Indicates the request url contains invalid query filter.",
++ "The requested url contains the invalid query filter.",
++ "Warning",
++ "Warning",
++ 0,
++ {},
++ "Ensure the correct query filter is specified in requested url "
++ "and resubmit the request if the operation failed.",
++ }},
+ MessageEntry{"MalformedJSON",
+ {
+ "Indicates that the request body was malformed JSON. "
+diff --git a/redfish-core/lib/event_service.hpp b/redfish-core/lib/event_service.hpp
+index f14c03e..b91b745 100644
+--- a/redfish-core/lib/event_service.hpp
++++ b/redfish-core/lib/event_service.hpp
+@@ -462,73 +462,110 @@ class EventServiceSSE : public Node
+ return;
+ }
+
+- std::shared_ptr<crow::Request::Adaptor> sseConn =
+- std::make_shared<crow::Request::Adaptor>(std::move(req.socket()));
+- std::shared_ptr<Subscription> subValue =
+- std::make_shared<Subscription>(sseConn);
+-
+- // GET on this URI means, Its SSE subscriptionType.
+- subValue->subscriptionType = subscriptionTypeSSE;
+-
+- // Default values
+- subValue->protocol = "Redfish";
+- subValue->retryPolicy = "TerminateAfterRetries";
+-
+- boost::urls::url_view::params_type::iterator it =
+- req.urlParams.find("$filter");
+- if (it == req.urlParams.end())
++ // It supports only "$filter" query param.
++ if (req.urlParams.size() > 1)
+ {
+- subValue->eventFormatType = "Event";
++ messages::invalidQueryFilter(res);
++ res.end();
++ return;
+ }
+
++ std::string eventFormatType;
++ std::string queryFilters;
++ if (req.urlParams.size())
++ {
++ boost::urls::url_view::params_type::iterator it =
++ req.urlParams.find("$filter");
++ if (it == req.urlParams.end())
++ {
++ messages::invalidQueryFilter(res);
++ res.end();
++ return;
++ }
++ else
++ {
++ queryFilters = it->value();
++ }
++ }
+ else
+ {
+- std::string filters = it->value();
+- // Reading from query params.
+- bool status = readSSEQueryParams(
+- filters, subValue->eventFormatType, subValue->registryMsgIds,
+- subValue->registryPrefixes, subValue->metricReportDefinitions);
++ eventFormatType = "Event";
++ }
+
++ std::vector<std::string> msgIds;
++ std::vector<std::string> regPrefixes;
++ std::vector<std::string> mrdsArray;
++ if (!queryFilters.empty())
++ {
++ // Reading from query params.
++ bool status = readSSEQueryParams(queryFilters, eventFormatType,
++ msgIds, regPrefixes, mrdsArray);
+ if (!status)
+ {
+- messages::invalidObject(res, filters);
++ messages::invalidObject(res, queryFilters);
++ res.end();
+ return;
+ }
+
+- if (!subValue->eventFormatType.empty())
++ // RegsitryPrefix and messageIds are mutuly exclusive as per redfish
++ // specification.
++ if (regPrefixes.size() && msgIds.size())
++ {
++ messages::mutualExclusiveProperties(res, "RegistryPrefix",
++ "MessageId");
++ res.end();
++ return;
++ }
++
++ if (!eventFormatType.empty())
+ {
+ if (std::find(supportedEvtFormatTypes.begin(),
+ supportedEvtFormatTypes.end(),
+- subValue->eventFormatType) ==
+- supportedEvtFormatTypes.end())
++ eventFormatType) == supportedEvtFormatTypes.end())
+ {
+- messages::propertyValueNotInList(
+- res, subValue->eventFormatType, "EventFormatType");
++ messages::propertyValueNotInList(res, eventFormatType,
++ "EventFormatType");
++ res.end();
+ return;
+ }
+ }
+ else
+ {
+ // If nothing specified, using default "Event"
+- subValue->eventFormatType.assign({"Event"});
++ eventFormatType.assign({"Event"});
+ }
+
+- if (!subValue->registryPrefixes.empty())
++ if (!regPrefixes.empty())
+ {
+- for (const std::string& it : subValue->registryPrefixes)
++ for (const std::string& it : regPrefixes)
+ {
+ if (std::find(supportedRegPrefixes.begin(),
+ supportedRegPrefixes.end(),
+ it) == supportedRegPrefixes.end())
+ {
+ messages::propertyValueNotInList(res, it,
+- "RegistryPrefixes");
++ "RegistryPrefix");
++ res.end();
+ return;
+ }
+ }
+ }
+ }
+
++ std::shared_ptr<crow::Request::Adaptor> sseConn =
++ std::make_shared<crow::Request::Adaptor>(std::move(req.socket()));
++ std::shared_ptr<Subscription> subValue =
++ std::make_shared<Subscription>(sseConn);
++
++ // GET on this URI means, Its SSE subscriptionType.
++ subValue->subscriptionType = subscriptionTypeSSE;
++ subValue->protocol = "Redfish";
++ subValue->retryPolicy = "TerminateAfterRetries";
++ subValue->eventFormatType = eventFormatType;
++ subValue->registryMsgIds = msgIds;
++ subValue->registryPrefixes = regPrefixes;
++ subValue->metricReportDefinitions = mrdsArray;
++
+ std::string id =
+ EventServiceManager::getInstance().addSubscription(subValue, false);
+ if (id.empty())
+diff --git a/redfish-core/src/error_messages.cpp b/redfish-core/src/error_messages.cpp
+index c6938ba..290d3f2 100644
+--- a/redfish-core/src/error_messages.cpp
++++ b/redfish-core/src/error_messages.cpp
+@@ -1779,6 +1779,32 @@ void mutualExclusiveProperties(crow::Response& res, const std::string& arg1,
+ addMessageToErrorJson(res.jsonValue, mutualExclusiveProperties(arg1, arg2));
+ }
+
++/**
++ * @internal
++ * @brief Formats InvalidQueryFilter into JSON
++ *
++ * See header file for more information
++ * @endinternal
++ */
++nlohmann::json invalidQueryFilter()
++{
++ return nlohmann::json{
++ {"@odata.type", "#Message.v1_0_0.Message"},
++ {"MessageId", "Base.1.5.0.InvalidQueryFilter"},
++ {"Message", "The requested url contains the invalid query filter."},
++ {"MessageArgs", nlohmann::json::array()},
++ {"Severity", "Warning"},
++ {"Resolution",
++ "Ensure the correct query filter is specified in requested url "
++ "and resubmit the request."}};
++}
++
++void invalidQueryFilter(crow::Response& res)
++{
++ res.result(boost::beast::http::status::bad_request);
++ addMessageToErrorJson(res.jsonValue, invalidQueryFilter());
++}
++
+ } // namespace messages
+
+ } // namespace redfish
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb_%.bbappend b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb_%.bbappend
index 5a44eec78..52598bf15 100644
--- a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb_%.bbappend
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb_%.bbappend
@@ -20,6 +20,21 @@ SRC_URI += "file://0001-Firmware-update-support-for-StandBySpare.patch \
file://0005-EventService-https-client-support.patch \
file://0005-VirtualMedia-fixes-for-Redfish-Service-Validator.patch \
file://0006-Fix-Image-and-ImageName-values-in-schema.patch \
+ file://0007-cpudimm-get-cpu-details-from-Redfish.patch \
+ file://0008-systems-Fix-for-Processor-Summary-Model.patch \
+ file://0009-Fix-MetricReportDefinitions-filter-not-working.patch \
+ file://0010-Fix-EventService-stops-sending-events.patch \
+ file://0011-Deallocate-memory-during-failed-case.patch \
+ file://0012-System-Replace-chassis-name-in-Redfish.patch \
+ file://0013-url_view-throws-if-a-parse-error-is-found.patch \
+ file://0014-add-sufficient-delay-to-create-fw-update-object.patch \
+ file://0009-Workaround-Fix-memory-leak.patch \
+ file://0015-Add-firmware-activation-messages-to-the-registry.patch \
+ file://0016-EventService-Fix-type-mismatch-in-MetricReport.patch \
+ file://0017-Add-MutualExclusiveProperties-registry.patch \
+ file://0018-Add-sse-event-sequence-number.patch \
+ file://0019-EventService-Limit-SSE-connections-as-per-design.patch \
+ file://0020-EventService-Validate-SSE-query-filters.patch \
"
# Temporary downstream mirror of upstream patches, see telemetry\README for details
@@ -28,7 +43,6 @@ SRC_URI += "file://telemetry/0001-Redfish-TelemetryService-schema-implementation
file://telemetry/0003-Add-support-for-DELETE-in-MetricReportDefinitions-st.patch \
file://telemetry/0004-Add-support-for-OnRequest-in-MetricReportDefinition.patch \
file://telemetry/0005-Add-support-for-MetricDefinition-scheme.patch \
- file://telemetry/0006-Fix-MetricReport-timestamp-for-EventService.patch \
"
# Temporary fix: Move it to service file
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0064-transporthandler-Fix-for-invalid-VLAN-id.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0064-transporthandler-Fix-for-invalid-VLAN-id.patch
new file mode 100644
index 000000000..6c55e54fe
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0064-transporthandler-Fix-for-invalid-VLAN-id.patch
@@ -0,0 +1,94 @@
+From 84c49dc17fecc69bdb88dbc7cfb4b67eff81a4e6 Mon Sep 17 00:00:00 2001
+From: jayaprakash Mutyala <mutyalax.jayaprakash@intel.com>
+Date: Mon, 18 May 2020 23:12:13 +0000
+Subject: [PATCH] transporthandler: Fix for invalid VLAN id
+
+Issue: Set LAN configuration, allowing invalid VLAN ID's and giving
+exception when user trying to set VLAN.
+
+Fix: Add condition to return proper error for invalid VLAN ID's and add
+a condition to skip exception temporarily.
+
+Tested:
+Verified using ipmitool raw commands
+Command: ipmitool raw 0x0c 0x01 0x1 0x14 0x00 0x80 //Set Lan, vlan id=0
+Response: Unable to send RAW command (channel=0x0 netfn=0xc lun=0x0
+ cmd=0x1 rsp=0xcc): Invalid data field in request
+Command: ipmitool raw 0x0c 0x01 0x1 0x14 0xff 0x8f
+ //Set Lan, vlan id=4095
+Response: Unable to send RAW command (channel=0x0 netfn=0xc lun=0x0
+ cmd=0x1 rsp=0xcc): Invalid data field in request
+Command: ipmitool raw 0x0c 0x01 0x1 0x14 0x00 0x82
+Response: //Success
+
+Command: ipmitool lan print 1
+Response:
+Set in Progress : Set Complete
+Auth Type Support :
+Auth Type Enable : Callback :
+ : User :
+ : Operator :
+ : Admin :
+ : OEM :
+IP Address Source : DHCP Address
+IP Address : 0.0.0.0
+Subnet Mask : 255.255.255.255
+MAC Address : a6:41:81:e8:39:33
+Default Gateway IP : 10.190.164.1
+Default Gateway MAC : 00:00:00:00:00:00
+802.1q VLAN ID : 512
+RMCP+ Cipher Suites : 17
+Cipher Suite Priv Max : aaaaaaaaaaaaaaa
+ : X=Cipher Suite Unused
+ : c=CALLBACK
+ : u=USER
+ : o=OPERATOR
+ : a=ADMIN
+ : O=OEM
+Bad Password Threshold : Not Available
+
+Command: ipmitool raw 0x0c 0x01 0x1 0x14 0x00 0x00
+Response: //Success
+Command: ipmitool lan print 1
+Response:
+......
+802.1q VLAN ID : Disabled
+
+Signed-off-by: jayaprakash Mutyala <mutyalax.jayaprakash@intel.com>
+Change-Id: I3d3fe1c9fa5d629fc88f13577d2ac138e9fd4933
+---
+ transporthandler.cpp | 10 ++++++++--
+ 1 file changed, 8 insertions(+), 2 deletions(-)
+
+diff --git a/transporthandler.cpp b/transporthandler.cpp
+index 3813d05..6e11535 100644
+--- a/transporthandler.cpp
++++ b/transporthandler.cpp
+@@ -772,7 +772,9 @@ void deleteObjectIfExists(sdbusplus::bus::bus& bus, const std::string& service,
+ }
+ catch (const sdbusplus::exception::SdBusError& e)
+ {
+- if (strcmp(e.name(), "org.freedesktop.DBus.Error.UnknownObject") != 0)
++ if (strcmp(e.name(),
++ "xyz.openbmc_project.Common.Error.InternalFailure") != 0 &&
++ strcmp(e.name(), "org.freedesktop.DBus.Error.UnknownObject") != 0)
+ {
+ // We want to rethrow real errors
+ throw;
+@@ -1538,8 +1540,12 @@ RspType<> setLan(Context::ptr ctx, uint4_t channelBits, uint4_t reserved1,
+ lastDisabledVlan[channel] = vlan;
+ vlan = 0;
+ }
+- channelCall<reconfigureVLAN>(channel, vlan);
++ else if (vlan == 0 || vlan == VLAN_VALUE_MASK)
++ {
++ return responseInvalidFieldRequest();
++ }
+
++ channelCall<reconfigureVLAN>(channel, vlan);
+ return responseSuccess();
+ }
+ case LanParam::CiphersuiteSupport:
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0065-apphandler-Fix-for-set-system-Info-parameter-cmd.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0065-apphandler-Fix-for-set-system-Info-parameter-cmd.patch
new file mode 100644
index 000000000..3366e309a
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0065-apphandler-Fix-for-set-system-Info-parameter-cmd.patch
@@ -0,0 +1,98 @@
+From 3c5e413b55e60bdf4c7c34d06485e00915a969dd Mon Sep 17 00:00:00 2001
+From: jayaprakash Mutyala <mutyalax.jayaprakash@intel.com>
+Date: Mon, 27 Apr 2020 23:00:05 +0000
+Subject: [PATCH] apphandler: Fix for set system Info parameter cmd
+
+Issue: Get System Info parameter command returning incorrect response if
+ set system info command set the values less than 16 bytes.
+
+Fix: Appending zero's if user setting less than 16 bytes data using set
+ system info parameter API.
+
+Tested:
+Before:
+Command: ipmitool raw 0x06 0x58 0x02 0x00 0x00 0x69 0x6e 0x74 0x65 0x6c
+ 0x2d 0x6f 0x70 0x65 0x6e 0x62 0x6d 0x63 //Set system info
+Response: //success
+Commands: ipmitool raw 0x06 0x59 0x00 0x02 0x00 0x00 //Get system info
+Response: 11 00 00 69 6e 74 65 6c 2d 6f 70 65 6e 62 6d 63
+ 2d 6d
+Commands: ipmitool raw 0x06 0x58 0x08 0x00 0x00 0x69 0x6e 0x74 0x65 0x6c
+ 0x2d 0x6f 0x70 0x65 0x6e 0x62 0x6d 0x63
+Response: //success
+Commands: ipmitool raw 0x06 0x58 0xff 0x00 0x00 0x69 0x6e 0x74 0x65 0x6c
+ 0x2d 0x6f 0x70 0x65 0x6e 0x62 0x6d 0x63 0x10
+Response: //success
+
+After:
+Commands: ipmitool raw 0x06 0x58 0x02 0x00 0x00 0x69 0x6e 0x74 0x65 0x6c
+ 0x2d 0x6f 0x70 0x65 0x6e 0x62 0x6d 0x63 //Set system info
+Response: //success
+Commands: ipmitool raw 0x06 0x59 0x00 0x02 0x00 0x00 //Get system info
+Response: 11 00 00 69 6e 74 65 6c 2d 6f 70 65 6e 62 6d 63
+ 00 00
+Commands: ipmitool raw 0x06 0x58 0x08 0x00 0x00 0x69 0x6e 0x74 0x65
+ 0x6c 0x2d 0x6f 0x70 0x65 0x6e 0x62 0x6d 0x63 //Set system info
+Response: Unable to send RAW command (channel=0x0 netfn=0x6 lun=0x0
+ cmd=0x58 rsp=0xcc): Invalid data field in request
+Commands: ipmitool raw 0x06 0x58 0xff 0x00 0x00 0x69 0x6e 0x74 0x65
+ 0x6c 0x2d 0x6f 0x70 0x65 0x6e 0x62 0x6d 0x63 0x10
+ //Set system info
+Response: Unable to send RAW command (channel=0x0 netfn=0x6 lun=0x0
+ cmd=0x58 rsp=0x80): Unknown (0x80)
+
+Signed-off-by: jayaprakash Mutyala <mutyalax.jayaprakash@intel.com>
+Change-Id: I10be443df0bd5828f447919f919a9824352cc36b
+---
+ apphandler.cpp | 21 +++++++++++++++++++++
+ 1 file changed, 21 insertions(+)
+
+diff --git a/apphandler.cpp b/apphandler.cpp
+index d567fe3..8baff39 100644
+--- a/apphandler.cpp
++++ b/apphandler.cpp
+@@ -89,6 +89,10 @@ static constexpr const char* cmdMaskStr = "commandMask";
+ static constexpr int base_16 = 16;
+ #endif // ENABLE_I2C_WHITELIST_CHECK
+ static constexpr uint8_t maxIPMIWriteReadSize = 144;
++static constexpr uint8_t oemCmdStart = 192;
++static constexpr uint8_t oemCmdEnd = 255;
++static constexpr uint8_t invalidParamSelectorStart = 8;
++static constexpr uint8_t invalidParamSelectorEnd = 191;
+
+ /**
+ * @brief Returns the Version info from primary s/w object
+@@ -1350,6 +1354,16 @@ ipmi::RspType<uint8_t, // Parameter revision
+ ipmi::RspType<> ipmiAppSetSystemInfo(uint8_t paramSelector, uint8_t data1,
+ std::vector<uint8_t> configData)
+ {
++ if (paramSelector >= invalidParamSelectorStart &&
++ paramSelector <= invalidParamSelectorEnd)
++ {
++ return ipmi::responseInvalidFieldRequest();
++ }
++ if ((paramSelector >= oemCmdStart) && (paramSelector <= oemCmdEnd))
++ {
++ return ipmi::responseParmNotSupported();
++ }
++
+ if (paramSelector == 0)
+ {
+ // attempt to set the 'set in progress' value (in parameter #0)
+@@ -1375,6 +1389,13 @@ ipmi::RspType<> ipmiAppSetSystemInfo(uint8_t paramSelector, uint8_t data1,
+ return ipmi::responseInvalidFieldRequest();
+ }
+
++ // Append zero's to remaining bytes
++ if (configData.size() < configParameterLength)
++ {
++ fill_n(back_inserter(configData),
++ (configParameterLength - configData.size()), 0x00);
++ }
++
+ if (!sysInfoParamStore)
+ {
+ sysInfoParamStore = std::make_unique<SysInfoParamStore>();
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0066-apphandler-Fix-for-total-session-slots-count.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0066-apphandler-Fix-for-total-session-slots-count.patch
new file mode 100644
index 000000000..fd32f30b4
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0066-apphandler-Fix-for-total-session-slots-count.patch
@@ -0,0 +1,64 @@
+From 80207e6202d0f2dad62e8c5d9e83704bfe68c07c Mon Sep 17 00:00:00 2001
+From: Jayaprakash Mutyala <mutyalax.jayaprakash@intel.com>
+Date: Sat, 4 Jul 2020 16:34:15 +0000
+Subject: [PATCH] apphandler: Fix for total session slots count
+
+Issue: Get session info shows 60 sessions as total number of sessions
+ for all medium_type as lan-802 channels instead actual sessions.
+
+Fix: Initialize the channel Info structure to empty to avoid wrong
+ calculation of total number of session slots for all channels
+ which are having medium_type as lan-802.
+
+Tested:
+Verified using ipmitool command.
+Before:
+Command: ipmitool -I lanplus -H <BMC-IP> -C 17 -U root -P <Password> session info all
+Response:
+session handle : 129
+slot count : 60
+active sessions : 1
+user id : 1
+privilege level : ADMINISTRATOR
+session type : IPMIv2/RMCP+
+channel number : 0x03
+console ip : 10.190.201.113
+console mac : 00:00:00:00:00:00
+console port : 42963
+
+After:
+Command: ipmitool -I lanplus -H <BMC-IP> -C 17 -U root -P <Password> session info all
+Response:
+session handle : 129
+slot count : 30
+active sessions : 1
+user id : 1
+privilege level : ADMINISTRATOR
+session type : IPMIv2/RMCP+
+channel number : 0x03
+console ip : 10.190.201.113
+console mac : 00:00:00:00:00:00
+console port : 48994
+
+Signed-off-by: Jayaprakash Mutyala <mutyalax.jayaprakash@intel.com>
+Change-Id: I9a4523bfbaeb0178f15e8b40f034b43d7ce4b8a0
+---
+ apphandler.cpp | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/apphandler.cpp b/apphandler.cpp
+index 8baff39..4ba637f 100644
+--- a/apphandler.cpp
++++ b/apphandler.cpp
+@@ -944,7 +944,7 @@ uint8_t getTotalSessionCount()
+ while (ch < ipmi::maxIpmiChannels &&
+ count < session::maxNetworkInstanceSupported)
+ {
+- ipmi::ChannelInfo chInfo;
++ ipmi::ChannelInfo chInfo{};
+ ipmi::getChannelInfo(ch, chInfo);
+ if (static_cast<ipmi::EChannelMediumType>(chInfo.mediumType) ==
+ ipmi::EChannelMediumType::lan8032)
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0067-Fix-for-get-Channel-Info-cmd-for-reserved-channels.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0067-Fix-for-get-Channel-Info-cmd-for-reserved-channels.patch
new file mode 100644
index 000000000..4b14110a6
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0067-Fix-for-get-Channel-Info-cmd-for-reserved-channels.patch
@@ -0,0 +1,61 @@
+From afd12b4ecc381e21b05e90368ccd29a96ff644b4 Mon Sep 17 00:00:00 2001
+From: Jayaprakash Mutyala <mutyalax.jayaprakash@intel.com>
+Date: Tue, 7 Jul 2020 01:06:57 +0000
+Subject: [PATCH] Fix for get Channel Info cmd for reserved channels
+
+Issue: Get channel info command returning improper response as "0x82"
+ which is not expected for reserved channels 5, 11, 12, 13.
+
+Fix: Return proper completion code for reserved channels.
+
+Tested:
+Verified using ipmitool raw commands
+Before:
+Command: ipmitool raw 6 0x42 0x05 //get Channel Info
+Response: Unable to send RAW command (channel=0x0 netfn=0x6 lun=0x0
+ cmd=0x42 rsp=0x82): Unknown (0x82)
+Command: ipmitool raw 6 0x42 0x0b
+Response: Unable to send RAW command (channel=0x0 netfn=0x6 lun=0x0
+ cmd=0x42 rsp=0x82): Unknown (0x82)
+Command: ipmitool raw 6 0x42 0x0c
+Response: Unable to send RAW command (channel=0x0 netfn=0x6 lun=0x0
+ cmd=0x42 rsp=0x82): Unknown (0x82)
+Command: ipmitool raw 6 0x42 0x0d
+Response: Unable to send RAW command (channel=0x0 netfn=0x6 lun=0x0
+ cmd=0x42 rsp=0x82): Unknown (0x82)
+After:
+Command: ipmitool raw 6 0x42 0x05 //get Channel Info
+Response: Unable to send RAW command (channel=0x0 netfn=0x6 lun=0x0
+ cmd=0x42 rsp=0xcc): Invalid data field in request
+Command: ipmitool raw 6 0x42 0x0b
+Response: Unable to send RAW command (channel=0x0 netfn=0x6 lun=0x0
+ cmd=0x42 rsp=0xcc): Invalid data field in request
+Command: ipmitool raw 6 0x42 0x0c
+Response: Unable to send RAW command (channel=0x0 netfn=0x6 lun=0x0
+ cmd=0x42 rsp=0xcc): Invalid data field in request
+Command: ipmitool raw 6 0x42 0x0d
+Response: Unable to send RAW command (channel=0x0 netfn=0x6 lun=0x0
+ cmd=0x42 rsp=0xcc): Invalid data field in request
+
+Signed-off-by: Jayaprakash Mutyala <mutyalax.jayaprakash@intel.com>
+Change-Id: Ic5a5bb2317ee301a1ecc37350cbe1b289d33ca38
+---
+ user_channel/channelcommands.cpp | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/user_channel/channelcommands.cpp b/user_channel/channelcommands.cpp
+index 4bf8071..6987e04 100644
+--- a/user_channel/channelcommands.cpp
++++ b/user_channel/channelcommands.cpp
+@@ -258,7 +258,7 @@ RspType<uint4_t, // chNum
+ if (!isValidChannel(chNum))
+ {
+ log<level::DEBUG>("Get channel Info - No support on channel");
+- return response(ccActionNotSupportedForChannel);
++ return responseInvalidFieldRequest();
+ }
+
+ ChannelInfo chInfo;
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0068-Removal-of-OEM-privilege-setting-for-User.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0068-Removal-of-OEM-privilege-setting-for-User.patch
new file mode 100644
index 000000000..d66f6fe32
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0068-Removal-of-OEM-privilege-setting-for-User.patch
@@ -0,0 +1,43 @@
+From 785223a6867f7914e9f549cf06655034eea95b4e Mon Sep 17 00:00:00 2001
+From: srikanta mondal <srikantax.mondal@intel.com>
+Date: Fri, 10 Apr 2020 11:35:32 +0000
+Subject: [PATCH] Removal of OEM privilege setting for User
+
+Issue: Set OEM user Privilege is success for Set user access command
+
+Fix: Set user access - provided fix to deny set OEM user privilege
+ for all channel.
+
+Tested:
+Before:
+Command: ipmitool raw 0x06 0x43 0x93 0x07 0x05 0x00 // Set user access
+Response: // Success
+
+After:
+Command: ipmitool raw 0x06 0x43 0x93 0x07 0x05 0x00 // Set user access
+Response: Unable to send RAW command (channel=0x0 netfn=0x6 lun=0x0
+ cmd=0x43 rsp=0xcc): Invalid data field in request
+
+Signed-off-by: srikanta mondal <srikantax.mondal@intel.com>
+Change-Id: Iec38bd15d087a34b2178b8b578dc599817b7e3d1
+---
+ user_channel/channel_layer.cpp | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/user_channel/channel_layer.cpp b/user_channel/channel_layer.cpp
+index 38fd43f..03b1729 100644
+--- a/user_channel/channel_layer.cpp
++++ b/user_channel/channel_layer.cpp
+@@ -45,7 +45,8 @@ bool doesDeviceExist(const uint8_t chNum)
+ bool isValidPrivLimit(const uint8_t privLimit)
+ {
+ // Callback privilege is deprecated in OpenBMC
+- return ((privLimit > PRIVILEGE_CALLBACK) && (privLimit <= PRIVILEGE_OEM));
++ // At present, "OEM Privilege" is not used in OpenBMC
++ return ((privLimit > PRIVILEGE_CALLBACK) && (privLimit < PRIVILEGE_OEM));
+ }
+
+ bool isValidAccessMode(const uint8_t accessMode)
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0069-apphandler-Fix-for-get-system-info-command.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0069-apphandler-Fix-for-get-system-info-command.patch
new file mode 100644
index 000000000..1d6410a6d
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0069-apphandler-Fix-for-get-system-info-command.patch
@@ -0,0 +1,89 @@
+From a5ae77282bdd60172f7ef1baca117069b8809bb5 Mon Sep 17 00:00:00 2001
+From: Snehalatha V <SnehalathaX.V@intel.com>
+Date: Sat, 2 May 2020 18:18:57 +0000
+Subject: [PATCH] apphandler: Fix for get system info command
+
+Issue: Get system info parameters command giving improper default
+ results for parameters 1,3,4,5,6,7.
+
+Fix: Provided fix to return proper default response
+
+Tested:
+Verified using ipmitool raw commands
+Command : ipmitool raw 0x06 0x59 0x00 0x01 0x00 0x00
+Response: Unable to send RAW command (channel=0x0 netfn=0x6 lun=0x0
+ cmd=0x59 rsp=0xcb): Requested sensor, data, or record not
+ found
+Command : ipmitool raw 0x06 0x59 0x00 0x02 0x00 0x00
+Response: 11 00 00 0a 69 6e 74 65 6c 2d 6f 62 6d 63 00 00
+ 00 00
+Command : ipmitool raw 0x06 0x59 0x00 0x03 0x00 0x00
+Response: Unable to send RAW command (channel=0x0 netfn=0x6 lun=0x0
+ cmd=0x59 rsp=0xcb): Requested sensor, data, or record not
+ found
+Command : ipmitool raw 0x06 0x59 0x00 0x07 0x00 0x00
+Response: Unable to send RAW command (channel=0x0 netfn=0x6 lun=0x0
+ cmd=0x59 rsp=0xcb): Requested sensor, data, or record not
+ found
+Command : ipmitool raw 0x06 0x59 0x00 0x08 0x00 0x00
+Response: Unable to send RAW command (channel=0x0 netfn=0x6 lun=0x0
+ cmd=0x59 rsp=0xcc): Invalid data field in request
+Command : ipmitool raw 0x06 0x59 0x00 0x3f 0x00 0x00
+Response: Unable to send RAW command (channel=0x0 netfn=0x6 lun=0x0
+ cmd=0x59 rsp=0xcc): Invalid data field in request
+
+Signed-off-by: Snehalatha V <SnehalathaX.V@intel.com>
+Change-Id: I2a98b91bad199dc4eeac68b68972c3355cb5ec2f
+---
+ apphandler.cpp | 18 +++++++++++++++---
+ 1 file changed, 15 insertions(+), 3 deletions(-)
+
+diff --git a/apphandler.cpp b/apphandler.cpp
+index 4ba637f..90818a9 100644
+--- a/apphandler.cpp
++++ b/apphandler.cpp
+@@ -1289,10 +1289,15 @@ ipmi::RspType<uint8_t, // Parameter revision
+ uint8_t paramSelector, uint8_t setSelector,
+ uint8_t BlockSelector)
+ {
+- if (reserved)
++ if (reserved || (paramSelector >= invalidParamSelectorStart &&
++ paramSelector <= invalidParamSelectorEnd))
+ {
+ return ipmi::responseInvalidFieldRequest();
+ }
++ if ((paramSelector >= oemCmdStart) && (paramSelector <= oemCmdEnd))
++ {
++ return ipmi::responseParmNotSupported();
++ }
+ if (getRevision)
+ {
+ return ipmi::responseSuccess(paramRevision, std::nullopt, std::nullopt);
+@@ -1322,7 +1327,7 @@ ipmi::RspType<uint8_t, // Parameter revision
+ bool found = std::get<0>(ret);
+ if (!found)
+ {
+- return ipmi::responseParmNotSupported();
++ return ipmi::responseSensorInvalid();
+ }
+ std::string& paramString = std::get<1>(ret);
+ std::vector<uint8_t> configData;
+@@ -1334,7 +1339,14 @@ ipmi::RspType<uint8_t, // Parameter revision
+ count = std::min(paramString.length(), smallChunkSize);
+ configData.resize(count + configDataOverhead);
+ std::copy_n(paramString.begin(), count,
+- configData.begin() + configDataOverhead); // 14 bytes thunk
++ configData.begin() + configDataOverhead); // 14 bytes chunk
++
++ // Append zero's to remaining bytes
++ if (configData.size() < configParameterLength)
++ {
++ std::fill_n(std::back_inserter(configData),
++ configParameterLength - configData.size(), 0x00);
++ }
+ }
+ else
+ {
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0070-minor-fix-corrected-cc-for-get-channel-access.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0070-minor-fix-corrected-cc-for-get-channel-access.patch
new file mode 100644
index 000000000..9d27c8dfc
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0070-minor-fix-corrected-cc-for-get-channel-access.patch
@@ -0,0 +1,39 @@
+From c4f4f7a6f541412a70483241395239f4652c8462 Mon Sep 17 00:00:00 2001
+From: AppaRao Puli <apparao.puli@linux.intel.com>
+Date: Mon, 13 Jul 2020 16:43:59 +0530
+Subject: [PATCH 1/4] minor fix: corrected cc for get channel access
+
+As per IPMI spec, get channel access don't have
+specific cc code 0x83(Access mode not supported).
+Whereas set channel access has that specific cc.
+So changed cc to generic 0xcc(invalid field request)
+in get channel access mode command.
+
+Tested:
+For reserved access mode byte 2 request, return 0xCC.
+ipmitool -I lanplus -U <> -P <> -H <IP> raw 6 0x41 0x01 0x00
+Unable to send RAW command (channel=0x0 netfn=0x6 lun=0x0
+cmd=0x41 rsp=0xcc): Invalid data field in request
+
+Change-Id: I75256b9f74eddaf95a9f78d95730332877d21dfd
+Signed-off-by: AppaRao Puli <apparao.puli@linux.intel.com>
+---
+ user_channel/channelcommands.cpp | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/user_channel/channelcommands.cpp b/user_channel/channelcommands.cpp
+index 6987e04..b774d3f 100644
+--- a/user_channel/channelcommands.cpp
++++ b/user_channel/channelcommands.cpp
+@@ -180,7 +180,7 @@ ipmi ::RspType<uint3_t, // access mode,
+ if ((accessSetMode == doNotSet) || (accessSetMode == reserved))
+ {
+ log<level::DEBUG>("Get channel access - Invalid Access mode");
+- return response(ccAccessModeNotSupportedForChannel);
++ return responseInvalidFieldRequest();
+ }
+
+ const uint8_t chNum =
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0071-chassishandler-SetSystemBootOptions-to-new-API.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0071-chassishandler-SetSystemBootOptions-to-new-API.patch
new file mode 100644
index 000000000..f6a9e9f35
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0071-chassishandler-SetSystemBootOptions-to-new-API.patch
@@ -0,0 +1,821 @@
+From 8133e8bd818f986a9c5d373b3c56683560103214 Mon Sep 17 00:00:00 2001
+From: Jayaprakash Mutyala <mutyalax.jayaprakash@intel.com>
+Date: Thu, 3 Sep 2020 19:53:10 +0000
+Subject: [PATCH] chassishandler: SetSystemBootOptions to new API
+
+Rewrite ipmiChassisSetSysBootOptions to use newly introduced IPMI
+provider API
+
+Tested:
+verified using IPMI chassis bootparam command and raw commands
+Command: ipmitool chassis bootparam set bootflag force_disk
+Response: Set Boot Device to force_disk
+Command: ipmitool chassis bootparam set bootflag force_pxe
+Response: Set Boot Device to force_pxe
+Command: ipmitool chassis bootdev pxe options=persistent
+Response: Set Boot Device to pxe
+Command: ipmitool chassis bootparam set bootflag force_bios
+Response: Set Boot Device to force_bios
+Command: ipmitool chassis bootparam set bootflag force_safe
+Response: Set Chassis Boot Parameter 5 failed: Invalid data field in
+ request
+
+Command: ipmitool raw 0 8 0x5 0 0 0 0 0 //setBootOptions param 5
+Response: //Success
+Command: ipmitool raw 0 8 0x4 0 0 //setBootOptions param 4
+Response: //Success
+Command: ipmitool raw 0 8 0x61 0x21 0x70 0x62 0x21 0x00 0x01
+ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+ 0x01 0x01 0x04 0 0 0 0 1 1 1 1 //setBootOptions param 61
+Response: //Success
+Command: ipmitool raw 0 8 0 0 //setBootOptions param 0
+Response: //Success
+
+Signed-off-by: srikanta mondal <srikantax.mondal@intel.com>
+Signed-off-by: Jayaprakash Mutyala <mutyalax.jayaprakash@intel.com>
+
+%% original patch: 0071-chassishandler-SetSystemBootOptions-to-new-API.patch
+---
+ chassishandler.cpp | 465 +++++++++++++++++++++++++++++----------------
+ chassishandler.hpp | 15 +-
+ 2 files changed, 305 insertions(+), 175 deletions(-)
+
+diff --git a/chassishandler.cpp b/chassishandler.cpp
+index f5e7375..ca7cd2c 100644
+--- a/chassishandler.cpp
++++ b/chassishandler.cpp
+@@ -35,37 +35,33 @@
+ #include <xyz/openbmc_project/State/Host/server.hpp>
+ #include <xyz/openbmc_project/State/PowerOnHours/server.hpp>
+
+-// Defines
+-#define SET_PARM_VERSION 0x01
+-#define SET_PARM_BOOT_FLAGS_PERMANENT 0x40
+-#define SET_PARM_BOOT_FLAGS_VALID_ONE_TIME 0x80
+-#define SET_PARM_BOOT_FLAGS_VALID_PERMANENT 0xC0
+-
+ std::unique_ptr<phosphor::Timer> identifyTimer
+ __attribute__((init_priority(101)));
+
+ static ChassisIDState chassisIDState = ChassisIDState::reserved;
+-
+-constexpr size_t SIZE_MAC = 18;
+-constexpr size_t SIZE_BOOT_OPTION = (uint8_t)
+- BootOptionResponseSize::OPAL_NETWORK_SETTINGS; // Maximum size of the boot
+- // option parametrs
+-constexpr size_t SIZE_PREFIX = 7;
+-constexpr size_t MAX_PREFIX_VALUE = 32;
+-constexpr size_t SIZE_COOKIE = 4;
+-constexpr size_t SIZE_VERSION = 2;
++static constexpr uint8_t setParmVersion = 0x01;
++static constexpr uint8_t setParmBootFlagsPermanent = 0x40;
++static constexpr uint8_t setParmBootFlagsValidOneTime = 0x80;
++static constexpr uint8_t setParmBootFlagsValidPermanent = 0xC0;
++
++constexpr size_t SIZE_BOOT_OPTION = static_cast<size_t>(
++ BootOptionResponseSize::opalNetworkSettings); // Maximum size of the boot
++ // option parameters
++constexpr size_t sizeVersion = 2;
+ constexpr size_t DEFAULT_IDENTIFY_TIME_OUT = 15;
+
+ // PetiBoot-Specific
+-static constexpr uint8_t net_conf_initial_bytes[] = {0x80, 0x21, 0x70, 0x62,
+- 0x21, 0x00, 0x01, 0x06};
+-
+-static constexpr size_t COOKIE_OFFSET = 1;
+-static constexpr size_t VERSION_OFFSET = 5;
+-static constexpr size_t ADDR_SIZE_OFFSET = 8;
+-static constexpr size_t MAC_OFFSET = 9;
+-static constexpr size_t ADDRTYPE_OFFSET = 16;
+-static constexpr size_t IPADDR_OFFSET = 17;
++static constexpr uint8_t netConfInitialBytes[] = {0x80, 0x21, 0x70, 0x62,
++ 0x21, 0x00, 0x01, 0x06};
++static constexpr uint8_t oemParmStart = 96;
++static constexpr uint8_t oemParmEnd = 127;
++
++static constexpr size_t cookieOffset = 1;
++static constexpr size_t versionOffset = 5;
++static constexpr size_t addrSizeOffset = 8;
++static constexpr size_t macOffset = 9;
++static constexpr size_t addrTypeOffset = 16;
++static constexpr size_t ipAddrOffset = 17;
+
+ static constexpr uint4_t RESERVED = 0;
+ static constexpr uint8_t CHANNEL_NOT_SUPPORTED = 0;
+@@ -75,6 +71,16 @@ static constexpr size_t chassisIdentifyReqLength = 2;
+ static constexpr size_t identifyIntervalPos = 0;
+ static constexpr size_t forceIdentifyPos = 1;
+
++namespace ipmi
++{
++constexpr Cc ccParmNotSupported = 0x80;
++
++static inline auto responseParmNotSupported()
++{
++ return response(ccParmNotSupported);
++}
++} // namespace ipmi
++
+ void register_netfn_chassis_functions() __attribute__((constructor));
+
+ // Host settings in dbus
+@@ -180,12 +186,6 @@ struct get_sys_boot_options_response_t
+ uint8_t data[SIZE_BOOT_OPTION];
+ } __attribute__((packed));
+
+-struct set_sys_boot_options_t
+-{
+- uint8_t parameter;
+- uint8_t data[SIZE_BOOT_OPTION];
+-} __attribute__((packed));
+-
+ int getHostNetworkData(get_sys_boot_options_response_t* respptr)
+ {
+ ipmi::PropertyMap properties;
+@@ -255,15 +255,15 @@ int getHostNetworkData(get_sys_boot_options_response_t* respptr)
+ }
+ }
+
+- sscanf(
+- MACAddress.c_str(), ipmi::network::MAC_ADDRESS_FORMAT,
+- (respptr->data + MAC_OFFSET), (respptr->data + MAC_OFFSET + 1),
+- (respptr->data + MAC_OFFSET + 2), (respptr->data + MAC_OFFSET + 3),
+- (respptr->data + MAC_OFFSET + 4), (respptr->data + MAC_OFFSET + 5));
++ sscanf(MACAddress.c_str(), ipmi::network::MAC_ADDRESS_FORMAT,
++ (respptr->data + macOffset), (respptr->data + macOffset + 1),
++ (respptr->data + macOffset + 2), (respptr->data + macOffset + 3),
++ (respptr->data + macOffset + 4),
++ (respptr->data + macOffset + 5));
+
+- respptr->data[MAC_OFFSET + 6] = 0x00;
++ respptr->data[macOffset + 6] = 0x00;
+
+- std::memcpy(respptr->data + ADDRTYPE_OFFSET, &isStatic,
++ std::memcpy(respptr->data + addrTypeOffset, &isStatic,
+ sizeof(isStatic));
+
+ uint8_t addressFamily = (std::get<std::string>(properties["Type"]) ==
+@@ -277,9 +277,9 @@ int getHostNetworkData(get_sys_boot_options_response_t* respptr)
+
+ // ipaddress and gateway would be in IPv4 format
+ inet_pton(addressFamily, ipAddress.c_str(),
+- (respptr->data + IPADDR_OFFSET));
++ (respptr->data + ipAddrOffset));
+
+- uint8_t prefixOffset = IPADDR_OFFSET + addrSize;
++ uint8_t prefixOffset = ipAddrOffset + addrSize;
+
+ std::memcpy(respptr->data + prefixOffset, &prefix, sizeof(prefix));
+
+@@ -298,10 +298,10 @@ int getHostNetworkData(get_sys_boot_options_response_t* respptr)
+
+ // PetiBoot-Specific
+ // If success then copy the first 9 bytes to the data
+- std::memcpy(respptr->data, net_conf_initial_bytes,
+- sizeof(net_conf_initial_bytes));
++ std::memcpy(respptr->data, netConfInitialBytes,
++ sizeof(netConfInitialBytes));
+
+- std::memcpy(respptr->data + ADDR_SIZE_OFFSET, &addrSize, sizeof(addrSize));
++ std::memcpy(respptr->data + addrSizeOffset, &addrSize, sizeof(addrSize));
+
+ #ifdef _IPMI_DEBUG_
+ std::printf("\n===Printing the IPMI Formatted Data========\n");
+@@ -361,19 +361,18 @@ std::string getAddrStr(uint8_t family, uint8_t* data, uint8_t offset,
+ return ipAddr;
+ }
+
+-int setHostNetworkData(set_sys_boot_options_t* reqptr)
++ipmi::Cc setHostNetworkData(ipmi::message::Payload& data)
+ {
+ using namespace std::string_literals;
+- std::string host_network_config;
+- char mac[]{"00:00:00:00:00:00"};
++ std::string hostNetworkConfig;
++ std::string mac("00:00:00:00:00:00");
+ std::string ipAddress, gateway;
+- char addrOrigin{0};
++ std::string addrOrigin{0};
+ uint8_t addrSize{0};
+ std::string addressOrigin =
+ "xyz.openbmc_project.Network.IP.AddressOrigin.DHCP";
+ std::string addressType = "xyz.openbmc_project.Network.IP.Protocol.IPv4";
+ uint8_t prefix{0};
+- uint32_t zeroCookie = 0;
+ uint8_t family = AF_INET;
+
+ // cookie starts from second byte
+@@ -384,13 +383,33 @@ int setHostNetworkData(set_sys_boot_options_t* reqptr)
+ do
+ {
+ // cookie == 0x21 0x70 0x62 0x21
+- if (memcmp(&(reqptr->data[COOKIE_OFFSET]),
+- (net_conf_initial_bytes + COOKIE_OFFSET),
+- SIZE_COOKIE) != 0)
++ data.trailingOk = true;
++ auto msgLen = data.size();
++ std::vector<uint8_t> msgPayloadBytes(msgLen);
++ if (data.unpack(msgPayloadBytes) != 0 || !data.fullyUnpacked())
++ {
++ log<level::ERR>(
++ "Error in unpacking message of setHostNetworkData");
++ return ipmi::ccReqDataLenInvalid;
++ }
++
++ uint8_t* msgPayloadStartingPos = msgPayloadBytes.data();
++ constexpr size_t cookieSize = 4;
++ if (msgLen < cookieOffset + cookieSize)
++ {
++ log<level::ERR>(
++ "Error in cookie getting of setHostNetworkData");
++ return ipmi::ccReqDataLenInvalid;
++ }
++ if (std::equal(msgPayloadStartingPos + cookieOffset,
++ msgPayloadStartingPos + cookieOffset + cookieSize,
++ (netConfInitialBytes + cookieOffset)) != 0)
+ {
+- // cookie == 0
+- if (memcmp(&(reqptr->data[COOKIE_OFFSET]), &zeroCookie,
+- SIZE_COOKIE) == 0)
++ // all cookie == 0
++ if (std::all_of(msgPayloadStartingPos + cookieOffset,
++ msgPayloadStartingPos + cookieOffset +
++ cookieSize,
++ [](int i) { return i == 0; }) == true)
+ {
+ // need to zero out the network settings.
+ break;
+@@ -401,59 +420,106 @@ int setHostNetworkData(set_sys_boot_options_t* reqptr)
+ }
+
+ // vesion == 0x00 0x01
+- if (memcmp(&(reqptr->data[VERSION_OFFSET]),
+- (net_conf_initial_bytes + VERSION_OFFSET),
+- SIZE_VERSION) != 0)
++ if (msgLen < versionOffset + sizeVersion)
++ {
++ log<level::ERR>(
++ "Error in version getting of setHostNetworkData");
++ return ipmi::ccReqDataLenInvalid;
++ }
++ if (std::equal(msgPayloadStartingPos + versionOffset,
++ msgPayloadStartingPos + versionOffset + sizeVersion,
++ (netConfInitialBytes + versionOffset)) != 0)
+ {
+-
+ log<level::ERR>("Invalid Version");
+ elog<InternalFailure>();
+ }
+
+- std::snprintf(
+- mac, SIZE_MAC, ipmi::network::MAC_ADDRESS_FORMAT,
+- reqptr->data[MAC_OFFSET], reqptr->data[MAC_OFFSET + 1],
+- reqptr->data[MAC_OFFSET + 2], reqptr->data[MAC_OFFSET + 3],
+- reqptr->data[MAC_OFFSET + 4], reqptr->data[MAC_OFFSET + 5]);
++ if (msgLen < macOffset + 6)
++ {
++ log<level::ERR>(
++ "Error in mac address getting of setHostNetworkData");
++ return ipmi::ccReqDataLenInvalid;
++ }
++ std::stringstream result;
++ std::copy((msgPayloadStartingPos + macOffset),
++ (msgPayloadStartingPos + macOffset + 5),
++ std::ostream_iterator<int>(result, ":"));
++ mac = result.str();
+
+- std::memcpy(&addrOrigin, &(reqptr->data[ADDRTYPE_OFFSET]),
+- sizeof(decltype(addrOrigin)));
++ if (msgLen < addrTypeOffset + sizeof(decltype(addrOrigin)))
++ {
++ log<level::ERR>(
++ "Error in original address getting of setHostNetworkData");
++ return ipmi::ccReqDataLenInvalid;
++ }
++ std::copy(msgPayloadStartingPos + addrTypeOffset,
++ msgPayloadStartingPos + addrTypeOffset +
++ sizeof(decltype(addrOrigin)),
++ std::ostream_iterator<int>(result, ""));
++ addrOrigin = result.str();
+
+- if (addrOrigin)
++ if (!addrOrigin.empty())
+ {
+ addressOrigin =
+ "xyz.openbmc_project.Network.IP.AddressOrigin.Static";
+ }
+
++ if (msgLen < addrSizeOffset + sizeof(decltype(addrSize)))
++ {
++ log<level::ERR>(
++ "Error in address size getting of setHostNetworkData");
++ return ipmi::ccReqDataLenInvalid;
++ }
+ // Get the address size
+- std::memcpy(&addrSize, &reqptr->data[ADDR_SIZE_OFFSET],
+- sizeof(addrSize));
++ std::copy(msgPayloadStartingPos + addrSizeOffset,
++ (msgPayloadStartingPos + addrSizeOffset +
++ sizeof(decltype(addrSize))),
++ &addrSize);
+
+- uint8_t prefixOffset = IPADDR_OFFSET + addrSize;
+-
+- std::memcpy(&prefix, &(reqptr->data[prefixOffset]),
+- sizeof(decltype(prefix)));
++ uint8_t prefixOffset = ipAddrOffset + addrSize;
++ if (msgLen < prefixOffset + sizeof(decltype(prefix)))
++ {
++ log<level::ERR>(
++ "Error in prefix getting of setHostNetworkData");
++ return ipmi::ccReqDataLenInvalid;
++ }
++ std::copy(msgPayloadStartingPos + prefixOffset,
++ (msgPayloadStartingPos + prefixOffset +
++ sizeof(decltype(prefix))),
++ &prefix);
+
+ uint8_t gatewayOffset = prefixOffset + sizeof(decltype(prefix));
+-
+ if (addrSize != ipmi::network::IPV4_ADDRESS_SIZE_BYTE)
+ {
+ addressType = "xyz.openbmc_project.Network.IP.Protocol.IPv6";
+ family = AF_INET6;
+ }
+
+- ipAddress =
+- getAddrStr(family, reqptr->data, IPADDR_OFFSET, addrSize);
++ if (msgLen < ipAddrOffset + addrSize)
++ {
++ log<level::ERR>(
++ "Error in IP address getting of setHostNetworkData");
++ return ipmi::ccReqDataLenInvalid;
++ }
++ ipAddress = getAddrStr(family, msgPayloadStartingPos, ipAddrOffset,
++ addrSize);
+
+- gateway = getAddrStr(family, reqptr->data, gatewayOffset, addrSize);
++ if (msgLen < gatewayOffset + addrSize)
++ {
++ log<level::ERR>(
++ "Error in gateway address getting of setHostNetworkData");
++ return ipmi::ccReqDataLenInvalid;
++ }
++ gateway = getAddrStr(family, msgPayloadStartingPos, gatewayOffset,
++ addrSize);
+
+ } while (0);
+
+ // Cookie == 0 or it is a valid cookie
+- host_network_config += "ipaddress="s + ipAddress + ",prefix="s +
+- std::to_string(prefix) + ",gateway="s + gateway +
+- ",mac="s + mac + ",addressOrigin="s +
+- addressOrigin;
++ hostNetworkConfig += "ipaddress="s + ipAddress + ",prefix="s +
++ std::to_string(prefix) + ",gateway="s + gateway +
++ ",mac="s + mac + ",addressOrigin="s +
++ addressOrigin;
+
+ sdbusplus::bus::bus bus(ipmid_get_sd_bus_connection());
+
+@@ -476,17 +542,17 @@ int setHostNetworkData(set_sys_boot_options_t* reqptr)
+ ipmi::setDbusProperty(bus, macObjectInfo.second, macObjectInfo.first,
+ MAC_INTERFACE, "MACAddress", std::string(mac));
+
+- log<level::DEBUG>(
+- "Network configuration changed",
+- entry("NETWORKCONFIG=%s", host_network_config.c_str()));
++ log<level::DEBUG>("Network configuration changed",
++ entry("NETWORKCONFIG=%s", hostNetworkConfig.c_str()));
+ }
+- catch (InternalFailure& e)
++ catch (sdbusplus::exception_t& e)
+ {
+ commit<InternalFailure>();
+- return -1;
++ log<level::ERR>("Error in ipmiChassisSetSysBootOptions call");
++ return ipmi::ccUnspecifiedError;
+ }
+
+- return 0;
++ return ipmi::ccSuccess;
+ }
+
+ uint32_t getPOHCounter()
+@@ -1444,7 +1510,7 @@ std::map<Mode::Modes, IpmiValue> modeDbusToIpmi = {
+ * @param[in] source - boot source value
+ * @return On failure return IPMI error.
+ */
+-static ipmi_ret_t setBootSource(const Source::Sources& source)
++static ipmi::Cc setBootSource(const Source::Sources& source)
+ {
+ using namespace chassis::internal;
+ using namespace chassis::internal::cache;
+@@ -1461,16 +1527,16 @@ static ipmi_ret_t setBootSource(const Source::Sources& source)
+ {
+ log<level::ERR>("Error in BootSource Set");
+ report<InternalFailure>();
+- return IPMI_CC_UNSPECIFIED_ERROR;
++ return ipmi::ccUnspecifiedError;
+ }
+- return IPMI_CC_OK;
++ return ipmi::ccSuccess;
+ }
+
+ /** @brief Set the property value for boot mode
+ * @param[in] mode - boot mode value
+ * @return On failure return IPMI error.
+ */
+-static ipmi_ret_t setBootMode(const Mode::Modes& mode)
++static ipmi::Cc setBootMode(const Mode::Modes& mode)
+ {
+ using namespace chassis::internal;
+ using namespace chassis::internal::cache;
+@@ -1487,9 +1553,9 @@ static ipmi_ret_t setBootMode(const Mode::Modes& mode)
+ {
+ log<level::ERR>("Error in BootMode Set");
+ report<InternalFailure>();
+- return IPMI_CC_UNSPECIFIED_ERROR;
++ return ipmi::ccUnspecifiedError;
+ }
+- return IPMI_CC_OK;
++ return ipmi::ccSuccess;
+ }
+
+ static constexpr uint8_t setComplete = 0x0;
+@@ -1511,29 +1577,28 @@ ipmi_ret_t ipmi_chassis_get_sys_boot_options(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+ IpmiValue bootOption = ipmiDefault;
+
+ if (reqptr->parameter ==
+- static_cast<uint8_t>(BootOptionParameter::SET_IN_PROGRESS))
++ static_cast<uint8_t>(BootOptionParameter::setInProgress))
+ {
+- *data_len =
+- static_cast<uint8_t>(BootOptionResponseSize::SET_IN_PROGRESS);
+- resp->version = SET_PARM_VERSION;
+- resp->parm = static_cast<uint8_t>(BootOptionParameter::SET_IN_PROGRESS);
++ *data_len = static_cast<uint8_t>(BootOptionResponseSize::setInProgress);
++ resp->version = setParmVersion;
++ resp->parm = static_cast<uint8_t>(BootOptionParameter::setInProgress);
+ resp->data[0] = transferStatus;
+ return IPMI_CC_OK;
+ }
+
+ std::memset(resp, 0, sizeof(*resp));
+- resp->version = SET_PARM_VERSION;
++ resp->version = setParmVersion;
+ resp->parm = 5;
+- resp->data[0] = SET_PARM_BOOT_FLAGS_VALID_ONE_TIME;
++ resp->data[0] = setParmBootFlagsValidOneTime;
+ /*
+ * Parameter #5 means boot flags. Please refer to 28.13 of ipmi doc.
+ * This is the only parameter used by petitboot.
+ */
+ if (reqptr->parameter ==
+- static_cast<uint8_t>(BootOptionParameter::BOOT_FLAGS))
++ static_cast<uint8_t>(BootOptionParameter::bootFlags))
+ {
+
+- *data_len = static_cast<uint8_t>(BootOptionResponseSize::BOOT_FLAGS);
++ *data_len = static_cast<uint8_t>(BootOptionResponseSize::bootFlags);
+ using namespace chassis::internal;
+ using namespace chassis::internal::cache;
+
+@@ -1592,9 +1657,8 @@ ipmi_ret_t ipmi_chassis_get_sys_boot_options(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+ }
+ resp->data[1] = (bootOption << 2);
+
+- resp->data[0] = oneTimeEnabled
+- ? SET_PARM_BOOT_FLAGS_VALID_ONE_TIME
+- : SET_PARM_BOOT_FLAGS_VALID_PERMANENT;
++ resp->data[0] = oneTimeEnabled ? setParmBootFlagsValidOneTime
++ : setParmBootFlagsValidPermanent;
+
+ rc = IPMI_CC_OK;
+ }
+@@ -1607,14 +1671,14 @@ ipmi_ret_t ipmi_chassis_get_sys_boot_options(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+ }
+ }
+ else if (reqptr->parameter ==
+- static_cast<uint8_t>(BootOptionParameter::OPAL_NETWORK_SETTINGS))
++ static_cast<uint8_t>(BootOptionParameter::opalNetworkSettings))
+ {
+
+ *data_len =
+- static_cast<uint8_t>(BootOptionResponseSize::OPAL_NETWORK_SETTINGS);
++ static_cast<uint8_t>(BootOptionResponseSize::opalNetworkSettings);
+
+ resp->parm =
+- static_cast<uint8_t>(BootOptionParameter::OPAL_NETWORK_SETTINGS);
++ static_cast<uint8_t>(BootOptionParameter::opalNetworkSettings);
+
+ int ret = getHostNetworkData(resp);
+
+@@ -1646,32 +1710,37 @@ ipmi_ret_t ipmi_chassis_get_sys_boot_options(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+ return rc;
+ }
+
+-ipmi_ret_t ipmi_chassis_set_sys_boot_options(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::RspType<> ipmiChassisSetSysBootOptions(ipmi::Context::ptr ctx,
++ uint7_t parameterSelector,
++ bool parameterIsValid,
++ ipmi::message::Payload& data)
+ {
+ using namespace boot_options;
+- ipmi_ret_t rc = IPMI_CC_OK;
+- set_sys_boot_options_t* reqptr = (set_sys_boot_options_t*)request;
+-
+- std::printf("IPMI SET_SYS_BOOT_OPTIONS reqptr->parameter =[%d]\n",
+- reqptr->parameter);
+-
+- // This IPMI command does not have any resposne data
+- *data_len = 0;
++ ipmi::Cc rc;
+
+- if (reqptr->parameter ==
+- static_cast<uint8_t>(BootOptionParameter::SET_IN_PROGRESS))
++ if (parameterSelector ==
++ static_cast<uint7_t>(BootOptionParameter::setInProgress))
+ {
++ uint2_t setStatus;
++ uint6_t rsvd;
++
++ if (data.unpack(rsvd, setStatus) != 0 || !data.fullyUnpacked())
++ {
++ return ipmi::responseReqDataLenInvalid();
++ }
++ if (rsvd || setStatus != static_cast<uint2_t>(setComplete))
++ {
++ return ipmi::responseInvalidFieldRequest();
++ }
+ if ((transferStatus == setInProgress) &&
+- (reqptr->data[0] != setComplete))
++ (static_cast<uint8_t>(setStatus) != setComplete))
+ {
+- return IPMI_CC_FAIL_SET_IN_PROGRESS;
++ constexpr ipmi::Cc ccFailSetInProgress = 0x81;
++ return ipmi::response(ccFailSetInProgress);
+ }
+- transferStatus = reqptr->data[0];
+- return IPMI_CC_OK;
++ transferStatus = static_cast<uint8_t>(setStatus);
++
++ return ipmi::responseSuccess();
+ }
+
+ /* 000101
+@@ -1679,9 +1748,37 @@ ipmi_ret_t ipmi_chassis_set_sys_boot_options(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+ * This is the only parameter used by petitboot.
+ */
+
+- if (reqptr->parameter == (uint8_t)BootOptionParameter::BOOT_FLAGS)
+- {
+- IpmiValue bootOption = ((reqptr->data[1] & 0x3C) >> 2);
++ if (parameterSelector ==
++ static_cast<uint7_t>(BootOptionParameter::bootFlags))
++ {
++ uint5_t rsvd;
++ bool validFlag;
++ bool permanent;
++ bool biosBootType;
++ bool lockOutResetButton;
++ bool screenBlank;
++ uint4_t bootDeviceSelector;
++ bool lockKeyboard;
++ bool cmosClear;
++ uint8_t data3;
++ uint4_t biosInfo;
++ uint4_t rsvd1;
++ uint5_t deviceInstance;
++ uint3_t rsvd2;
++
++ if (data.unpack(rsvd, biosBootType, permanent, validFlag,
++ lockOutResetButton, screenBlank, bootDeviceSelector,
++ lockKeyboard, cmosClear, data3, biosInfo, rsvd1,
++ deviceInstance, rsvd2) != 0 ||
++ !data.fullyUnpacked())
++ {
++ return ipmi::responseReqDataLenInvalid();
++ }
++ if (rsvd || rsvd1 || rsvd2)
++ {
++ return ipmi::responseInvalidFieldRequest();
++ }
++
+ using namespace chassis::internal;
+ using namespace chassis::internal::cache;
+ auto oneTimeEnabled = false;
+@@ -1691,10 +1788,6 @@ ipmi_ret_t ipmi_chassis_set_sys_boot_options(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+
+ try
+ {
+- bool permanent =
+- (reqptr->data[0] & SET_PARM_BOOT_FLAGS_PERMANENT) ==
+- SET_PARM_BOOT_FLAGS_PERMANENT;
+-
+ settings::Objects& objects = getObjects();
+
+ auto bootSetting = settings::boot::setting(objects, bootSourceIntf);
+@@ -1720,15 +1813,19 @@ ipmi_ret_t ipmi_chassis_set_sys_boot_options(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+ "Enabled", !permanent);
+ }
+
+- auto modeItr = modeIpmiToDbus.find(bootOption);
+- auto sourceItr = sourceIpmiToDbus.find(bootOption);
++ auto modeItr =
++ modeIpmiToDbus.find(static_cast<uint8_t>(bootDeviceSelector));
++ auto sourceItr =
++ sourceIpmiToDbus.find(static_cast<uint8_t>(bootDeviceSelector));
+ if (sourceIpmiToDbus.end() != sourceItr)
+ {
+ rc = setBootSource(sourceItr->second);
+- if (rc != IPMI_CC_OK)
++
++ if (rc != ipmi::ccSuccess)
+ {
+- *data_len = 0;
+- return rc;
++ log<level::ERR>("ipmiChassisSetSysBootOptions: Error in "
++ "setting boot source");
++ return ipmi::responseUnspecifiedError();
+ }
+ // If a set boot device is mapping to a boot source, then reset
+ // the boot mode D-Bus property to default.
+@@ -1742,10 +1839,11 @@ ipmi_ret_t ipmi_chassis_set_sys_boot_options(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+ if (modeIpmiToDbus.end() != modeItr)
+ {
+ rc = setBootMode(modeItr->second);
+- if (rc != IPMI_CC_OK)
++ if (rc != ipmi::ccSuccess)
+ {
+- *data_len = 0;
+- return rc;
++ log<level::ERR>("ipmiChassisSetSysBootOptions: Error in "
++ "setting boot mode");
++ return ipmi::responseUnspecifiedError();
+ }
+ // If a set boot device is mapping to a boot mode, then reset
+ // the boot source D-Bus property to default.
+@@ -1760,48 +1858,79 @@ ipmi_ret_t ipmi_chassis_set_sys_boot_options(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+ (sourceIpmiToDbus.end() == sourceItr))
+ {
+ // return error if boot option is not supported
+- *data_len = 0;
+- return IPMI_CC_INVALID_FIELD_REQUEST;
++ log<level::ERR>(
++ "ipmiChassisSetSysBootOptions: Boot option not supported");
++ return ipmi::responseInvalidFieldRequest();
+ }
+ }
+- catch (InternalFailure& e)
++ catch (sdbusplus::exception_t& e)
+ {
+ objectsPtr.reset();
+ report<InternalFailure>();
+- *data_len = 0;
+- return IPMI_CC_UNSPECIFIED_ERROR;
++ log<level::ERR>(
++ "ipmiChassisSetSysBootOptions: Error in setting Boot "
++ "flag parameters");
++ return ipmi::responseUnspecifiedError();
+ }
+ }
+- else if (reqptr->parameter ==
+- (uint8_t)BootOptionParameter::OPAL_NETWORK_SETTINGS)
++ else if (parameterSelector ==
++ static_cast<uint7_t>(BootOptionParameter::bootInfo))
+ {
++ uint8_t writeMak;
++ uint5_t bootInitiatorAckData;
++ uint3_t rsvd;
+
+- int ret = setHostNetworkData(reqptr);
+- if (ret < 0)
++ if (data.unpack(writeMak, bootInitiatorAckData, rsvd) != 0 ||
++ !data.fullyUnpacked())
+ {
+- log<level::ERR>(
+- "setHostNetworkData failed for set_sys_boot_options");
+- rc = IPMI_CC_UNSPECIFIED_ERROR;
++ return ipmi::responseReqDataLenInvalid();
+ }
+- }
+- else if (reqptr->parameter ==
+- static_cast<uint8_t>(BootOptionParameter::BOOT_INFO))
+- {
+- // Handle parameter #4 and return command completed normally
+- // (IPMI_CC_OK). There is no implementation in OpenBMC for this
++ if (rsvd)
++ {
++ return ipmi::responseInvalidFieldRequest();
++ }
++ // (ccSuccess). There is no implementation in OpenBMC for this
+ // parameter. This is added to support the ipmitool command `chassis
+ // bootdev` which sends set on parameter #4, before setting the boot
+ // flags.
+- rc = IPMI_CC_OK;
++ log<level::INFO>("ipmiChassisSetSysBootOptions: bootInfo parameter set "
++ "successfully");
++ data.trailingOk = true;
++ return ipmi::responseSuccess();
+ }
+ else
+ {
+- log<level::ERR>("Unsupported parameter",
+- entry("PARAM=0x%x", reqptr->parameter));
+- rc = IPMI_CC_PARM_NOT_SUPPORTED;
++ if ((parameterSelector >= static_cast<uint7_t>(oemParmStart)) &&
++ (parameterSelector <= static_cast<uint7_t>(oemParmEnd)))
++ {
++ if (parameterSelector ==
++ static_cast<uint7_t>(BootOptionParameter::opalNetworkSettings))
++ {
++ ipmi::Cc ret = setHostNetworkData(data);
++ if (ret != ipmi::ccSuccess)
++ {
++ log<level::ERR>("ipmiChassisSetSysBootOptions: Error in "
++ "setHostNetworkData");
++ data.trailingOk = true;
++ return ipmi::response(ret);
++ }
++ data.trailingOk = true;
++ return ipmi::responseSuccess();
++ }
++ else
++ {
++ log<level::ERR>(
++ "ipmiChassisSetSysBootOptions: Unsupported parameters",
++ entry("PARAM=0x%x",
++ static_cast<uint8_t>(parameterSelector)));
++ data.trailingOk = true;
++ return ipmi::responseParmNotSupported();
++ }
++ }
++ data.trailingOk = true;
++ return ipmi::responseParmNotSupported();
+ }
+-
+- return rc;
++ return ipmi::responseSuccess();
+ }
+
+ /** @brief implements Get POH counter command
+@@ -1963,9 +2092,11 @@ void register_netfn_chassis_functions()
+ ipmi::Privilege::Operator, ipmiChassisIdentify);
+
+ // <Set System Boot Options>
+- ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_SET_SYS_BOOT_OPTIONS, NULL,
+- ipmi_chassis_set_sys_boot_options,
+- PRIVILEGE_OPERATOR);
++ ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnChassis,
++ ipmi::chassis::cmdSetSystemBootOptions,
++ ipmi::Privilege::Operator,
++ ipmiChassisSetSysBootOptions);
++
+ // <Get POH Counter>
+ ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnChassis,
+ ipmi::chassis::cmdGetPohCounter,
+diff --git a/chassishandler.hpp b/chassishandler.hpp
+index 353a929..479563a 100644
+--- a/chassishandler.hpp
++++ b/chassishandler.hpp
+@@ -25,7 +25,6 @@ enum ipmi_chassis_return_codes
+ {
+ IPMI_OK = 0x0,
+ IPMI_CC_PARM_NOT_SUPPORTED = 0x80,
+- IPMI_CC_FAIL_SET_IN_PROGRESS = 0x81,
+ };
+
+ // Generic completion codes,
+@@ -47,17 +46,17 @@ enum ipmi_chassis_control_cmds : uint8_t
+ };
+ enum class BootOptionParameter : size_t
+ {
+- SET_IN_PROGRESS = 0x0,
+- BOOT_INFO = 0x4,
+- BOOT_FLAGS = 0x5,
+- OPAL_NETWORK_SETTINGS = 0x61
++ setInProgress = 0x0,
++ bootInfo = 0x4,
++ bootFlags = 0x5,
++ opalNetworkSettings = 0x61
+ };
+
+ enum class BootOptionResponseSize : size_t
+ {
+- SET_IN_PROGRESS = 3,
+- BOOT_FLAGS = 5,
+- OPAL_NETWORK_SETTINGS = 50
++ setInProgress = 3,
++ bootFlags = 5,
++ opalNetworkSettings = 50
+ };
+
+ enum class ChassisIDState : uint8_t
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0072-chassishandler-GetSystemBootOptions-to-new-API.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0072-chassishandler-GetSystemBootOptions-to-new-API.patch
new file mode 100644
index 000000000..272626e07
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0072-chassishandler-GetSystemBootOptions-to-new-API.patch
@@ -0,0 +1,429 @@
+From cab3769b39ae6f3cce0119fce2c823ec8e11af11 Mon Sep 17 00:00:00 2001
+From: Jayaprakash Mutyala <mutyalax.jayaprakash@intel.com>
+Date: Fri, 4 Sep 2020 12:53:17 +0000
+Subject: [PATCH] chassishandler: GetSystemBootOptions to new API
+
+Rewrite ipmiChassisGetSytemBootOptions to use newly introduced
+IPMI provider API
+
+Tested:
+Verified using ipmi chassis bootparam command
+
+Command: ipmitool chassis bootparam get 0
+Response:
+Boot parameter version: 0
+Boot parameter 0 is valid/unlocked
+Boot parameter data:
+ Set In Progress : set complete
+
+Command: ipmitool chassis bootparam get 5
+Response:
+Boot parameter version: 1
+Boot parameter 5 is valid/unlocked
+Boot parameter data: 8008000000
+ Boot Flags :
+ - Boot Flag Valid
+ - Options apply to only next boot
+ - BIOS PC Compatible (legacy) boot
+ - Boot Device Selector : Force Boot from default Hard-Drive
+ - BIOS verbosity : System Default
+ - Console Redirection control : 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: srikanta mondal <srikantax.mondal@intel.com>
+Signed-off-by: Jayaprakash Mutyala <mutyalax.jayaprakash@intel.com>
+---
+ chassishandler.cpp | 231 +++++++++++++++++++++++----------------------
+ chassishandler.hpp | 7 --
+ 2 files changed, 119 insertions(+), 119 deletions(-)
+
+diff --git a/chassishandler.cpp b/chassishandler.cpp
+index ca7cd2c..bbb3f81 100644
+--- a/chassishandler.cpp
++++ b/chassishandler.cpp
+@@ -44,9 +44,6 @@ static constexpr uint8_t setParmBootFlagsPermanent = 0x40;
+ static constexpr uint8_t setParmBootFlagsValidOneTime = 0x80;
+ static constexpr uint8_t setParmBootFlagsValidPermanent = 0xC0;
+
+-constexpr size_t SIZE_BOOT_OPTION = static_cast<size_t>(
+- BootOptionResponseSize::opalNetworkSettings); // Maximum size of the boot
+- // option parameters
+ constexpr size_t sizeVersion = 2;
+ constexpr size_t DEFAULT_IDENTIFY_TIME_OUT = 15;
+
+@@ -172,21 +169,7 @@ constexpr auto minutesPerCount = 60;
+
+ } // namespace poh
+
+-struct get_sys_boot_options_t
+-{
+- uint8_t parameter;
+- uint8_t set;
+- uint8_t block;
+-} __attribute__((packed));
+-
+-struct get_sys_boot_options_response_t
+-{
+- uint8_t version;
+- uint8_t parm;
+- uint8_t data[SIZE_BOOT_OPTION];
+-} __attribute__((packed));
+-
+-int getHostNetworkData(get_sys_boot_options_response_t* respptr)
++int getHostNetworkData(ipmi::message::Payload& payload)
+ {
+ ipmi::PropertyMap properties;
+ int rc = 0;
+@@ -238,7 +221,6 @@ int getHostNetworkData(get_sys_boot_options_response_t* respptr)
+ // don't send blank override.
+ if ((MACAddress == ipmi::network::DEFAULT_MAC_ADDRESS))
+ {
+- std::memset(respptr->data, 0, SIZE_BOOT_OPTION);
+ rc = -1;
+ return rc;
+ }
+@@ -249,22 +231,27 @@ int getHostNetworkData(get_sys_boot_options_response_t* respptr)
+ if ((ipAddress == ipmi::network::DEFAULT_ADDRESS) ||
+ (gateway == ipmi::network::DEFAULT_ADDRESS) || (!prefix))
+ {
+- std::memset(respptr->data, 0, SIZE_BOOT_OPTION);
+ rc = -1;
+ return rc;
+ }
+ }
+
+- sscanf(MACAddress.c_str(), ipmi::network::MAC_ADDRESS_FORMAT,
+- (respptr->data + macOffset), (respptr->data + macOffset + 1),
+- (respptr->data + macOffset + 2), (respptr->data + macOffset + 3),
+- (respptr->data + macOffset + 4),
+- (respptr->data + macOffset + 5));
++ std::string token;
++ std::stringstream ss(MACAddress);
++
++ // First pack macOffset no of bytes in payload.
++ // Latter this PetiBoot-Specific data will be populated.
++ std::vector<uint8_t> payloadInitialBytes(macOffset);
++ payload.pack(payloadInitialBytes);
++
++ while (std::getline(ss, token, ':'))
++ {
++ payload.pack(stoi(token, nullptr, 16));
++ }
+
+- respptr->data[macOffset + 6] = 0x00;
++ payload.pack(0x00);
+
+- std::memcpy(respptr->data + addrTypeOffset, &isStatic,
+- sizeof(isStatic));
++ payload.pack(isStatic);
+
+ uint8_t addressFamily = (std::get<std::string>(properties["Type"]) ==
+ "xyz.openbmc_project.Network.IP.Protocol.IPv4")
+@@ -276,39 +263,58 @@ int getHostNetworkData(get_sys_boot_options_response_t* respptr)
+ : ipmi::network::IPV6_ADDRESS_SIZE_BYTE;
+
+ // ipaddress and gateway would be in IPv4 format
++ std::vector<uint8_t> addrInBinary(addrSize);
+ inet_pton(addressFamily, ipAddress.c_str(),
+- (respptr->data + ipAddrOffset));
++ reinterpret_cast<void*>(addrInBinary.data()));
+
+- uint8_t prefixOffset = ipAddrOffset + addrSize;
++ payload.pack(addrInBinary);
+
+- std::memcpy(respptr->data + prefixOffset, &prefix, sizeof(prefix));
+-
+- uint8_t gatewayOffset = prefixOffset + sizeof(decltype(prefix));
++ payload.pack(prefix);
+
++ std::vector<uint8_t> gatewayDetails(addrSize);
+ inet_pton(addressFamily, gateway.c_str(),
+- (respptr->data + gatewayOffset));
++ reinterpret_cast<void*>(gatewayDetails.data()));
++ payload.pack(gatewayDetails);
+ }
+ catch (InternalFailure& e)
+ {
+ commit<InternalFailure>();
+- std::memset(respptr->data, 0, SIZE_BOOT_OPTION);
+ rc = -1;
+ return rc;
+ }
+
+ // PetiBoot-Specific
+- // If success then copy the first 9 bytes to the data
+- std::memcpy(respptr->data, netConfInitialBytes,
+- sizeof(netConfInitialBytes));
++ // If success then copy the first 9 bytes to the payload message
++ // payload first 2 bytes contain the parameter values. Skip that 2 bytes.
++ uint8_t skipFirstTwoBytes = 2;
++ size_t payloadSize = payload.size();
++ uint8_t* configDataStartingAddress = payload.data() + skipFirstTwoBytes;
+
+- std::memcpy(respptr->data + addrSizeOffset, &addrSize, sizeof(addrSize));
++ if (payloadSize < skipFirstTwoBytes + sizeof(netConfInitialBytes))
++ {
++ log<level::ERR>("Invalid net config ");
++ rc = -1;
++ return rc;
++ }
++ std::copy(netConfInitialBytes,
++ netConfInitialBytes + sizeof(netConfInitialBytes),
++ configDataStartingAddress);
++
++ if (payloadSize < skipFirstTwoBytes + addrSizeOffset + sizeof(addrSize))
++ {
++ log<level::ERR>("Invalid length of address size");
++ rc = -1;
++ return rc;
++ }
++ std::copy(&addrSize, &(addrSize) + sizeof(addrSize),
++ configDataStartingAddress + addrSizeOffset);
+
+ #ifdef _IPMI_DEBUG_
+ std::printf("\n===Printing the IPMI Formatted Data========\n");
+
+ for (uint8_t pos = 0; pos < index; pos++)
+ {
+- std::printf("%02x ", respptr->data[pos]);
++ std::printf("%02x ", payloadStartingAddress[pos]);
+ }
+ #endif
+
+@@ -1561,44 +1567,52 @@ static ipmi::Cc setBootMode(const Mode::Modes& mode)
+ static constexpr uint8_t setComplete = 0x0;
+ static constexpr uint8_t setInProgress = 0x1;
+ static uint8_t transferStatus = setComplete;
++/** @brief implements the Get Chassis system boot option
++ * @param bootOptionParameter - boot option parameter selector
++ * @param reserved1 - reserved bit
++ * @param setSelector - selects a particular block or set of parameters
++ * under the given parameter selector
++ * write as 00h if parameter doesn't use a setSelector
++ * @param blockSelector- selects a particular block within a set of
++ * parameters write as 00h if parameter doesn't use a
++ * blockSelector
++ *
++ * @return IPMI completion code plus response data
++ * @return Payload contains below parameters:
++ * version - parameter version
++ * bootOptionParameter - boot option parameter selector
++ * parmIndicator - parameter vaild/invaild indicator
++ * data - configuration parameter data
++ */
++ipmi::RspType<ipmi::message::Payload>
++ ipmiChassisGetSysBootOptions(uint7_t bootOptionParameter, bool reserved1,
+
+-ipmi_ret_t ipmi_chassis_get_sys_boot_options(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+- ipmi_request_t request,
+- ipmi_response_t response,
+- ipmi_data_len_t data_len,
+- ipmi_context_t context)
++ uint8_t setSelector, uint8_t blockSelector)
+ {
++ if (reserved1)
++ {
++ return ipmi::responseInvalidFieldRequest();
++ }
++
++ constexpr uint4_t version = 0x01;
++ ipmi::message::Payload response;
++ response.pack(version, uint4_t{});
+ using namespace boot_options;
+- ipmi_ret_t rc = IPMI_CC_PARM_NOT_SUPPORTED;
+- char* p = NULL;
+- get_sys_boot_options_response_t* resp =
+- (get_sys_boot_options_response_t*)response;
+- get_sys_boot_options_t* reqptr = (get_sys_boot_options_t*)request;
+- IpmiValue bootOption = ipmiDefault;
+
+- if (reqptr->parameter ==
++ IpmiValue bootOption = ipmiDefault;
++ if (static_cast<uint8_t>(bootOptionParameter) ==
+ static_cast<uint8_t>(BootOptionParameter::setInProgress))
+ {
+- *data_len = static_cast<uint8_t>(BootOptionResponseSize::setInProgress);
+- resp->version = setParmVersion;
+- resp->parm = static_cast<uint8_t>(BootOptionParameter::setInProgress);
+- resp->data[0] = transferStatus;
+- return IPMI_CC_OK;
++ return ipmi::response(transferStatus);
+ }
+
+- std::memset(resp, 0, sizeof(*resp));
+- resp->version = setParmVersion;
+- resp->parm = 5;
+- resp->data[0] = setParmBootFlagsValidOneTime;
+ /*
+ * Parameter #5 means boot flags. Please refer to 28.13 of ipmi doc.
+ * This is the only parameter used by petitboot.
+ */
+- if (reqptr->parameter ==
++ if (static_cast<uint8_t>(bootOptionParameter) ==
+ static_cast<uint8_t>(BootOptionParameter::bootFlags))
+ {
+-
+- *data_len = static_cast<uint8_t>(BootOptionResponseSize::bootFlags);
+ using namespace chassis::internal;
+ using namespace chassis::internal::cache;
+
+@@ -1619,8 +1633,7 @@ ipmi_ret_t ipmi_chassis_get_sys_boot_options(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+ {
+ log<level::ERR>("Error in BootSource Get");
+ report<InternalFailure>();
+- *data_len = 0;
+- return IPMI_CC_UNSPECIFIED_ERROR;
++ return ipmi::responseUnspecifiedError();
+ }
+ std::variant<std::string> result;
+ reply.read(result);
+@@ -1638,8 +1651,7 @@ ipmi_ret_t ipmi_chassis_get_sys_boot_options(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+ {
+ log<level::ERR>("Error in BootMode Get");
+ report<InternalFailure>();
+- *data_len = 0;
+- return IPMI_CC_UNSPECIFIED_ERROR;
++ return ipmi::responseUnspecifiedError();
+ }
+ reply.read(result);
+ auto bootMode =
+@@ -1655,59 +1667,54 @@ ipmi_ret_t ipmi_chassis_get_sys_boot_options(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+ {
+ bootOption = modeDbusToIpmi.at(bootMode);
+ }
+- resp->data[1] = (bootOption << 2);
+
+- resp->data[0] = oneTimeEnabled ? setParmBootFlagsValidOneTime
+- : setParmBootFlagsValidPermanent;
+-
+- rc = IPMI_CC_OK;
++ uint8_t bootOptionParam = oneTimeEnabled
++ ? setParmBootFlagsValidOneTime
++ : setParmBootFlagsValidPermanent;
++ response.pack(bootOptionParameter, reserved1, bootOptionParam,
++ uint2_t{}, uint4_t{bootOption}, uint2_t{}, uint8_t{},
++ uint8_t{}, uint8_t{});
++ return ipmi::responseSuccess(std::move(response));
+ }
+ catch (InternalFailure& e)
+ {
+ cache::objectsPtr.reset();
+ report<InternalFailure>();
+- *data_len = 0;
+- return IPMI_CC_UNSPECIFIED_ERROR;
++ return ipmi::responseUnspecifiedError();
+ }
+ }
+- else if (reqptr->parameter ==
+- static_cast<uint8_t>(BootOptionParameter::opalNetworkSettings))
++ else
+ {
+-
+- *data_len =
+- static_cast<uint8_t>(BootOptionResponseSize::opalNetworkSettings);
+-
+- resp->parm =
+- static_cast<uint8_t>(BootOptionParameter::opalNetworkSettings);
+-
+- int ret = getHostNetworkData(resp);
+-
+- if (ret < 0)
++ if ((bootOptionParameter >= oemParmStart) &&
++ (bootOptionParameter <= oemParmEnd))
+ {
+-
+- log<level::ERR>(
+- "getHostNetworkData failed for get_sys_boot_options.");
+- rc = IPMI_CC_UNSPECIFIED_ERROR;
++ if (static_cast<uint8_t>(bootOptionParameter) ==
++ static_cast<uint8_t>(BootOptionParameter::opalNetworkSettings))
++ {
++ response.pack(bootOptionParameter, reserved1);
++ int ret = getHostNetworkData(response);
++ if (ret < 0)
++ {
++ response.trailingOk = true;
++ log<level::ERR>(
++ "getHostNetworkData failed for GetSysBootOptions.");
++ return ipmi::responseUnspecifiedError();
++ }
++ else
++ {
++ return ipmi::responseSuccess(std::move(response));
++ }
++ }
+ }
+ else
+- rc = IPMI_CC_OK;
+- }
+-
+- else
+- {
+- log<level::ERR>("Unsupported parameter",
+- entry("PARAM=0x%x", reqptr->parameter));
+- }
+-
+- if (p)
+- free(p);
+-
+- if (rc == IPMI_CC_OK)
+- {
+- *data_len += 2;
++ {
++ log<level::ERR>(
++ "Unsupported parameter",
++ entry("PARAM=0x%x", static_cast<uint8_t>(bootOptionParameter)));
++ return ipmi::responseUnspecifiedError();
++ }
+ }
+-
+- return rc;
++ return ipmi::responseUnspecifiedError();
+ }
+
+ ipmi::RspType<> ipmiChassisSetSysBootOptions(ipmi::Context::ptr ctx,
+@@ -1820,7 +1827,6 @@ ipmi::RspType<> ipmiChassisSetSysBootOptions(ipmi::Context::ptr ctx,
+ if (sourceIpmiToDbus.end() != sourceItr)
+ {
+ rc = setBootSource(sourceItr->second);
+-
+ if (rc != ipmi::ccSuccess)
+ {
+ log<level::ERR>("ipmiChassisSetSysBootOptions: Error in "
+@@ -2067,9 +2073,10 @@ void register_netfn_chassis_functions()
+ ipmi::Privilege::User, ipmiSetChassisCap);
+
+ // <Get System Boot Options>
+- ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_GET_SYS_BOOT_OPTIONS, NULL,
+- ipmi_chassis_get_sys_boot_options,
+- PRIVILEGE_OPERATOR);
++ ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnChassis,
++ ipmi::chassis::cmdGetSystemBootOptions,
++ ipmi::Privilege::Operator,
++ ipmiChassisGetSysBootOptions);
+
+ // <Get Chassis Status>
+ ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnChassis,
+diff --git a/chassishandler.hpp b/chassishandler.hpp
+index 479563a..92c165e 100644
+--- a/chassishandler.hpp
++++ b/chassishandler.hpp
+@@ -20,13 +20,6 @@ enum ipmi_netfn_chassis_cmds
+ IPMI_CMD_GET_POH_COUNTER = 0x0F,
+ };
+
+-// Command specific completion codes
+-enum ipmi_chassis_return_codes
+-{
+- IPMI_OK = 0x0,
+- IPMI_CC_PARM_NOT_SUPPORTED = 0x80,
+-};
+-
+ // Generic completion codes,
+ // see IPMI doc section 5.2
+ enum ipmi_generic_return_codes
+--
+2.17.1
+
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
index 98420b2ef..afd9fdcf1 100644
--- 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
@@ -10,6 +10,15 @@ SRC_URI += "file://phosphor-ipmi-host.service \
file://0062-Update-IPMI-Chassis-Control-command.patch \
file://0063-Save-the-pre-timeout-interrupt-in-dbus-property.patch \
file://0001-Modify-Get-Lan-Configuration-IP-Address-Source-to-us.patch \
+ file://0064-transporthandler-Fix-for-invalid-VLAN-id.patch \
+ file://0065-apphandler-Fix-for-set-system-Info-parameter-cmd.patch \
+ file://0066-apphandler-Fix-for-total-session-slots-count.patch \
+ file://0067-Fix-for-get-Channel-Info-cmd-for-reserved-channels.patch \
+ file://0068-Removal-of-OEM-privilege-setting-for-User.patch \
+ file://0069-apphandler-Fix-for-get-system-info-command.patch \
+ file://0070-minor-fix-corrected-cc-for-get-channel-access.patch \
+ file://0071-chassishandler-SetSystemBootOptions-to-new-API.patch \
+ file://0072-chassishandler-GetSystemBootOptions-to-new-API.patch \
"
EXTRA_OECONF_append = " --disable-i2c-whitelist-check"
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-net/0009-Add-dbus-interface-for-sol-commands.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-net/0009-Add-dbus-interface-for-sol-commands.patch
index dc7f7357c..5f749af45 100644
--- a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-net/0009-Add-dbus-interface-for-sol-commands.patch
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-net/0009-Add-dbus-interface-for-sol-commands.patch
@@ -1,4 +1,4 @@
-From 97c21a556702a0d65096b30c07ef23f15cb6a7d9 Mon Sep 17 00:00:00 2001
+From e5ab844259f569656e95f5324f7428229dd811a7 Mon Sep 17 00:00:00 2001
From: Cheng C Yang <cheng.c.yang@intel.com>
Date: Wed, 3 Jul 2019 07:39:47 +0800
Subject: [PATCH] Add dbus interface for sol commands
@@ -25,18 +25,18 @@ to 0 and other properties will not reset to default value.
Signed-off-by: Cheng C Yang <cheng.c.yang@intel.com>
---
- command/payload_cmds.cpp | 3 ++
- command/sol_cmds.cpp | 84 -------------------------------
- sol/sol_manager.cpp | 125 +++++++++++++++++++++++++++++++++++++++++++++++
+ command/payload_cmds.cpp | 3 +
+ command/sol_cmds.cpp | 84 --------------------------
+ sol/sol_manager.cpp | 124 +++++++++++++++++++++++++++++++++++++++
sol/sol_manager.hpp | 1 +
- sol_module.cpp | 6 ---
- 5 files changed, 129 insertions(+), 90 deletions(-)
+ sol_module.cpp | 6 --
+ 5 files changed, 128 insertions(+), 90 deletions(-)
diff --git a/command/payload_cmds.cpp b/command/payload_cmds.cpp
-index c32a510..17167a7 100644
+index c8e682e..bc987c5 100644
--- a/command/payload_cmds.cpp
+++ b/command/payload_cmds.cpp
-@@ -34,6 +34,9 @@ std::vector<uint8_t> activatePayload(const std::vector<uint8_t>& inPayload,
+@@ -41,6 +41,9 @@ std::vector<uint8_t> activatePayload(const std::vector<uint8_t>& inPayload,
return outPayload;
}
@@ -47,10 +47,10 @@ index c32a510..17167a7 100644
{
response->completionCode = IPMI_CC_PAYLOAD_TYPE_DISABLED;
diff --git a/command/sol_cmds.cpp b/command/sol_cmds.cpp
-index a8fa410..804b5ea 100644
+index fda3e91..a1e820f 100644
--- a/command/sol_cmds.cpp
+++ b/command/sol_cmds.cpp
-@@ -65,90 +65,6 @@ void activating(uint8_t payloadInstance, uint32_t sessionID)
+@@ -71,90 +71,6 @@ void activating(uint8_t payloadInstance, uint32_t sessionID)
outPayload);
}
@@ -142,14 +142,12 @@ index a8fa410..804b5ea 100644
const message::Handler& handler)
{
diff --git a/sol/sol_manager.cpp b/sol/sol_manager.cpp
-index 2046fe4..eedd28a 100644
+index a118457..55d269a 100644
--- a/sol/sol_manager.cpp
+++ b/sol/sol_manager.cpp
-@@ -12,7 +12,13 @@
- #include <boost/asio/write.hpp>
- #include <chrono>
+@@ -14,6 +14,11 @@
#include <cmath>
-+#include <ipmid/utils.hpp>
+ #include <ipmid/utils.hpp>
#include <phosphor-logging/log.hpp>
+#include <sdbusplus/message/types.hpp>
+
@@ -159,7 +157,7 @@ index 2046fe4..eedd28a 100644
namespace sol
{
-@@ -93,6 +99,125 @@ void Manager::stopHostConsole()
+@@ -103,6 +108,125 @@ void Manager::stopHostConsole()
}
}
@@ -286,10 +284,10 @@ index 2046fe4..eedd28a 100644
session::SessionID sessionID)
{
diff --git a/sol/sol_manager.hpp b/sol/sol_manager.hpp
-index 5d96890..00da9fb 100644
+index 5b48add..4e797d4 100644
--- a/sol/sol_manager.hpp
+++ b/sol/sol_manager.hpp
-@@ -248,6 +248,7 @@ class Manager
+@@ -252,6 +252,7 @@ class Manager
* @return 0 on success and errno on failure.
*/
int writeConsoleSocket(const std::vector<uint8_t>& input) const;
@@ -315,5 +313,5 @@ index 8200e74..2b1fb46 100644
{{(static_cast<uint32_t>(message::PayloadType::IPMI) << 16) |
static_cast<uint16_t>(::command::NetFns::TRANSPORT) | 0x22},
--
-2.7.4
+2.17.1
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
index 10d0d8c94..fcf8df18d 100644
--- 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
@@ -3,7 +3,7 @@ inherit useradd
# TODO: This should be removed, once up-stream bump up
# issue is resolved
SRC_URI += "git://github.com/openbmc/phosphor-net-ipmid"
-SRCREV = "ecb32fbc699aaacee4d6a42bb986575c4c5780dc"
+SRCREV = "2b1edef0b1e395591dcf751d7ccf45a85bb58d4c"
USERADD_PACKAGES = "${PN}"
# add a group called ipmi
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
index ac45a8114..daa64f159 100644
--- a/meta-openbmc-mods/meta-common/recipes-phosphor/sensors/dbus-sensors_%.bbappend
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/sensors/dbus-sensors_%.bbappend
@@ -1,4 +1,4 @@
-SRCREV = "623723b9e827f52a05cfe2dac8b4ef5d285fb6af"
+SRCREV = "2456dde72421cd4086ac43e619fb0817a55bf0a7"
#SRC_URI = "git://github.com/openbmc/dbus-sensors.git"
DEPENDS_append = " libgpiod libmctp"
diff --git a/meta-openbmc-mods/meta-wht/recipes-core/host-error-monitor/host-error-monitor/0002-Add-a-workaround-for-spurious-CPU-errors.patch b/meta-openbmc-mods/meta-wht/recipes-core/host-error-monitor/host-error-monitor/0002-Add-a-workaround-for-spurious-CPU-errors.patch
new file mode 100644
index 000000000..2a573311f
--- /dev/null
+++ b/meta-openbmc-mods/meta-wht/recipes-core/host-error-monitor/host-error-monitor/0002-Add-a-workaround-for-spurious-CPU-errors.patch
@@ -0,0 +1,133 @@
+From d0e4130b2d1e0e44efc8fd6e180487853625edd6 Mon Sep 17 00:00:00 2001
+From: "Jason M. Bills" <jason.m.bills@intel.com>
+Date: Mon, 17 Aug 2020 15:52:22 -0700
+Subject: [PATCH] Add a workaround for spurious CPU errors
+
+There is a possible issue where GPIO event interrupts are getting
+missed causing false errors to be logged.
+
+This adds a check that the host is still on and the error is still
+asserted before logging an error.
+
+Tested:
+Confirmed that a spurious SMI event was ignored correctly after
+this change.
+
+Change-Id: Id83d9d67b15dcf9035e6448086b140e5c7dab4fe
+Signed-off-by: Jason M. Bills <jason.m.bills@intel.com>
+---
+ src/host_error_monitor.cpp | 77 ++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 77 insertions(+)
+
+diff --git a/src/host_error_monitor.cpp b/src/host_error_monitor.cpp
+index ca089f70d..fd453ccdc 100644
+--- a/src/host_error_monitor.cpp
++++ b/src/host_error_monitor.cpp
+@@ -797,6 +797,18 @@ static void caterrAssertHandler()
+ }
+ return;
+ }
++ // Confirm that this is a real failure by checking that the host is on
++ if (hostOff)
++ {
++ return;
++ }
++ // And that the signal is still asserted
++ if (caterrLine.get_value() != 0)
++ {
++ std::cerr
++ << "CPU_CATERR not asserted after timeout. Error ignored.\n";
++ return;
++ }
+ std::cerr << "CATERR asserted for " << std::to_string(caterrTimeoutMs)
+ << " ms\n";
+ beep(beepCPUIERR);
+@@ -1270,6 +1282,48 @@ static void errXAssertHandler(const int errPin,
+ }
+ return;
+ }
++ // Confirm that this is a real failure by checking that the host is on
++ if (hostOff)
++ {
++ return;
++ }
++ // And that the signal is still asserted
++ switch (errPin)
++ {
++ case 0:
++ {
++ if (err0Line.get_value() != 0)
++ {
++ std::cerr << "CPU_ERR0 not asserted after timeout. Error "
++ "ignored.\n";
++ return;
++ }
++ break;
++ }
++ case 1:
++ {
++ if (err1Line.get_value() != 0)
++ {
++ std::cerr << "CPU_ERR1 not asserted after timeout. Error "
++ "ignored.\n";
++ return;
++ }
++ break;
++ }
++ case 2:
++ {
++ if (err2Line.get_value() != 0)
++ {
++ std::cerr << "CPU_ERR2 not asserted after timeout. Error "
++ "ignored.\n";
++ return;
++ }
++ break;
++ }
++ default:
++ std::cerr << "Invalid ERR pin asserted\n";
++ return;
++ }
+ std::cerr << "ERR" << std::to_string(errPin) << " asserted for "
+ << std::to_string(errTimeoutMs) << " ms\n";
+ if (errPinCPUs.count())
+@@ -1379,6 +1433,18 @@ static void err2AssertHandler()
+ }
+ return;
+ }
++ // Confirm that this is a real failure by checking that the host is on
++ if (hostOff)
++ {
++ return;
++ }
++ // And that the signal is still asserted
++ if (err2Line.get_value() != 0)
++ {
++ std::cerr
++ << "CPU_ERR2 not asserted after timeout. Error ignored.\n";
++ return;
++ }
+ conn->async_method_call(
+ [](boost::system::error_code ec,
+ const std::variant<bool>& property) {
+@@ -1447,6 +1513,17 @@ static void smiAssertHandler()
+ }
+ return;
+ }
++ // Confirm that this is a real failure by checking that the host is on
++ if (hostOff)
++ {
++ return;
++ }
++ // And that the signal is still asserted
++ if (smiLine.get_value() != 0)
++ {
++ std::cerr << "SMI not asserted after timeout. Error ignored.\n";
++ return;
++ }
+ std::cerr << "SMI asserted for " << std::to_string(smiTimeoutMs)
+ << " ms\n";
+ smiTimeoutLog();
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-wht/recipes-core/host-error-monitor/host-error-monitor/0003-Override-crashdump-timeout-to-30-minutes.patch b/meta-openbmc-mods/meta-wht/recipes-core/host-error-monitor/host-error-monitor/0003-Override-crashdump-timeout-to-30-minutes.patch
new file mode 100644
index 000000000..7511cc218
--- /dev/null
+++ b/meta-openbmc-mods/meta-wht/recipes-core/host-error-monitor/host-error-monitor/0003-Override-crashdump-timeout-to-30-minutes.patch
@@ -0,0 +1,41 @@
+From 6d3f28619226c0dbfca6feb320a2fa292aa11f40 Mon Sep 17 00:00:00 2001
+From: "Jason M. Bills" <jason.m.bills@intel.com>
+Date: Wed, 2 Sep 2020 18:23:00 -0700
+Subject: [PATCH] Override crashdump timeout to 30 minutes
+
+The current crashdump timeout is set to 5 minutes, so if it takes
+longer than 5 minutes to complete the crashdump, then
+host-error-monitor will not reset the system to recover from the
+error.
+
+My current crashdump on a single socket is taking about 11 minutes
+to complete. This is a workaround to change the timeout to 30
+minutes to give enough time for crashdump to complete before timing
+out.
+
+Tested:
+Confirmed that when I inject an IERR on my system, it will correctly
+reset after 11 minutes when crashdump completes.
+
+Change-Id: I36ac3f0c83ae1634e486d9f8413b38fae5efb561
+Signed-off-by: Jason M. Bills <jason.m.bills@intel.com>
+---
+ src/host_error_monitor.cpp | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/host_error_monitor.cpp b/src/host_error_monitor.cpp
+index fd453ccdc..9dabb52bb 100644
+--- a/src/host_error_monitor.cpp
++++ b/src/host_error_monitor.cpp
+@@ -46,7 +46,7 @@ static size_t caterrTimeoutMs = 2000;
+ const static constexpr size_t caterrTimeoutMsMax = 600000; // 10 minutes maximum
+ const static constexpr size_t errTimeoutMs = 90000;
+ const static constexpr size_t smiTimeoutMs = 90000;
+-const static constexpr size_t crashdumpTimeoutS = 300;
++const static constexpr size_t crashdumpTimeoutS = 1800;
+
+ // Timers
+ // Timer for CATERR asserted
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-wht/recipes-core/host-error-monitor/host-error-monitor_%.bbappend b/meta-openbmc-mods/meta-wht/recipes-core/host-error-monitor/host-error-monitor_%.bbappend
index 4b79757c0..9853a4abc 100644
--- a/meta-openbmc-mods/meta-wht/recipes-core/host-error-monitor/host-error-monitor_%.bbappend
+++ b/meta-openbmc-mods/meta-wht/recipes-core/host-error-monitor/host-error-monitor_%.bbappend
@@ -2,4 +2,6 @@ FILESEXTRAPATHS_append := "${THISDIR}/${PN}:"
SRC_URI += " \
file://0001-Filter-memory-thermtrip-events-based-on-DIMM-status.patch \
+ file://0002-Add-a-workaround-for-spurious-CPU-errors.patch \
+ file://0003-Override-crashdump-timeout-to-30-minutes.patch \
"