summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason M. Bills <jason.m.bills@linux.intel.com>2020-08-31 23:56:28 +0300
committerJason M. Bills <jason.m.bills@linux.intel.com>2020-09-02 00:21:46 +0300
commitf99301c1a626951ee7feee081a1494e795d0e243 (patch)
treeca75379d317be9cc1757a00e0352a048b5d3200b
parent40108db4434d8c2e0a1ad2d1dd3f5ae34b17352c (diff)
downloadopenbmc-f99301c1a626951ee7feee081a1494e795d0e243.tar.xz
Update to internal 0.74
Signed-off-by: Jason M. Bills <jason.m.bills@linux.intel.com>
-rw-r--r--meta-openbmc-mods/meta-ast2500/conf/machine/include/intel-ast2500.inc5
-rw-r--r--meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0045-Apply-WDT1-2-reset-mask-to-reset-needed-controller.patch17
-rw-r--r--meta-openbmc-mods/meta-ast2500/recipes-phosphor/configuration/entity-manager/CPC-Baseboard.json36
-rw-r--r--meta-openbmc-mods/meta-ast2500/recipes-phosphor/configuration/entity-manager/WC-Baseboard.json12
-rw-r--r--meta-openbmc-mods/meta-ast2500/recipes-phosphor/configuration/entity-manager/WP-Baseboard.json36
-rw-r--r--meta-openbmc-mods/meta-ast2600/recipes-bsp/u-boot/files/0019-Apply-WDT-reset-mask-to-reset-needed-controller.patch78
-rw-r--r--meta-openbmc-mods/meta-ast2600/recipes-bsp/u-boot/files/0019-Apply-WDT1-2-reset-mask-to-reset-needed-controller.patch98
-rw-r--r--meta-openbmc-mods/meta-ast2600/recipes-bsp/u-boot/u-boot-aspeed-sdk_%.bbappend2
-rw-r--r--meta-openbmc-mods/meta-ast2600/recipes-phosphor/configuration/entity-manager/AC-Baseboard.json14
-rw-r--r--meta-openbmc-mods/meta-common/classes/image_types_intel_pfr.bbclass99
-rw-r--r--meta-openbmc-mods/meta-common/recipes-core/crashdump/crashdump_git.bb2
-rw-r--r--meta-openbmc-mods/meta-common/recipes-core/interfaces/libmctp_git.bb2
-rw-r--r--meta-openbmc-mods/meta-common/recipes-core/ipmi/intel-ipmi-oem_%.bbappend2
-rw-r--r--meta-openbmc-mods/meta-common/recipes-extended/sdbusplus/sdbusplus/0001-sdbusplus-settable-timeout-value-for-async_method_ca.patch134
-rw-r--r--meta-openbmc-mods/meta-common/recipes-extended/sdbusplus/sdbusplus/0002-sdbusplus_Add_new_signal_and_extend_set_property_methods.patch78
-rw-r--r--meta-openbmc-mods/meta-common/recipes-extended/sdbusplus/sdbusplus_%.bbappend6
-rw-r--r--meta-openbmc-mods/meta-common/recipes-graphics/libvncserver/libvncserver_%.bbappend2
-rw-r--r--meta-openbmc-mods/meta-common/recipes-graphics/obmc-ikvm/obmc-ikvm/0004-Connect-HID-gadget-device-dynamically.patch494
-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/host-misc-comm-manager/host-misc-comm-manager_git.bb2
-rw-r--r--meta-openbmc-mods/meta-common/recipes-intel/hsbp/hsbp-manager_git.bb2
-rwxr-xr-xmeta-openbmc-mods/meta-common/recipes-intel/intel-pfr/files/pfr_image.py65
-rw-r--r--meta-openbmc-mods/meta-common/recipes-intel/intel-pfr/pfr-manager_%.bbappend4
-rw-r--r--meta-openbmc-mods/meta-common/recipes-intel/smbios/smbios-mdrv2.bb6
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0001-arm-dts-intel-s2600wf-dts-fixups.patch477
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0095-pwm-and-tach-driver-changes-for-ast2600.patch2
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0116-watchdog-aspeed-fix-AST2600-support.patch45
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0118-Recalculate-AW-FCS-on-WrEndPointConfig-command.patch34
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/intel.cfg1
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed_%.bbappend2
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/configuration/entity-manager_%.bbappend2
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0028-MCTP-Daemon-D-Bus-interface-definition.patch41
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/fans/phosphor-pid-control_%.bbappend2
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0013-remove-image-file-on-pre-script-failures.patch40
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager_%.bbappend3
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0004-Remove-QueryString.patch621
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0004-bmcweb-handle-device-or-resource-busy-exception.patch219
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0005-EventService-https-client-support.patch405
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0005-VirtualMedia-fixes-for-Redfish-Service-Validator.patch122
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0006-Fix-Image-and-ImageName-values-in-schema.patch38
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0001-Redfish-TelemetryService-schema-implementation.patch913
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0002-Add-support-for-POST-in-MetricReportDefinitions.patch594
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0003-Add-support-for-DELETE-in-MetricReportDefinitions-st.patch68
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0004-Add-support-for-OnRequest-in-MetricReportDefinition.patch169
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0005-Add-support-for-MetricDefinition-scheme.patch535
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0006-Fix-MetricReport-timestamp-for-EventService.patch78
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/README21
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb_%.bbappend29
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/pmci/libmctp-intel_git.bb2
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/pmci/mctp-emulator.bb2
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/pmci/mctpd.bb2
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/sel-logger/phosphor-sel-logger_%.bbappend2
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/sensors/dbus-sensors_%.bbappend2
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/service-config-manager/service-config-manager_%.bbappend5
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/settings/settings_git.bb2
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/special-mode-mgr/special-mode-mgr_git.bb2
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/virtual-media/virtual-media.bb3
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/webui/phosphor-webui_%.bbappend2
-rw-r--r--meta-openbmc-mods/meta-common/recipes-support/boost-url/boost-url_git.bb17
-rwxr-xr-xmeta-openbmc-mods/meta-common/recipes-x86/chassis/x86-power-control_%.bbappend4
-rw-r--r--meta-openbmc-mods/meta-wht/recipes-core/host-error-monitor/host-error-monitor/0001-Filter-memory-thermtrip-events-based-on-DIMM-status.patch153
-rw-r--r--meta-openbmc-mods/meta-wht/recipes-core/host-error-monitor/host-error-monitor_%.bbappend5
62 files changed, 5630 insertions, 231 deletions
diff --git a/meta-openbmc-mods/meta-ast2500/conf/machine/include/intel-ast2500.inc b/meta-openbmc-mods/meta-ast2500/conf/machine/include/intel-ast2500.inc
index 1889831c8..3e7bd152f 100644
--- a/meta-openbmc-mods/meta-ast2500/conf/machine/include/intel-ast2500.inc
+++ b/meta-openbmc-mods/meta-ast2500/conf/machine/include/intel-ast2500.inc
@@ -1,5 +1,8 @@
KMACHINE = "aspeed"
-KERNEL_DEVICETREE = "${KMACHINE}-bmc-intel-ast2500.dtb"
+KERNEL_DEVICETREE = " \
+ ${KMACHINE}-bmc-intel-ast2500.dtb \
+ ${KMACHINE}-bmc-intel-s2600wf.dtb \
+ "
require conf/machine/include/ast2500.inc
require conf/machine/include/obmc-bsp-si-common.inc
diff --git a/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0045-Apply-WDT1-2-reset-mask-to-reset-needed-controller.patch b/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0045-Apply-WDT1-2-reset-mask-to-reset-needed-controller.patch
index ea7a582df..94e93db7f 100644
--- a/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0045-Apply-WDT1-2-reset-mask-to-reset-needed-controller.patch
+++ b/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0045-Apply-WDT1-2-reset-mask-to-reset-needed-controller.patch
@@ -23,13 +23,12 @@ in order to avoid the host hang.
1. SDRAM controller
2. AHB Bridges
3. Graphics CRT controller
-4. Reset Video Engine
-5. LPC controller
-6. CRT mode 2D Engine
-7. PWM controller
-8. MCTP Controller
-9. X- DMA Controller
-10. SPI controller
+4. LPC controller
+5. CRT mode 2D Engine
+6. PWM controller
+7. MCTP Controller
+8. X- DMA Controller
+9. SPI controller
Quick Step to reproduce:
Stop the BMC in uboot and add below bootcmd command
@@ -71,10 +70,10 @@ index b404353..97253f4 100644
str r1, [r0]
ldr r0, =0x1e78501c @ restore normal mask setting
- ldr r1, =0x023FFFF3 @ added 2016.09.06
-+ ldr r1, =0x023CD773 @ Changed 2020.06.18
++ ldr r1, =0x023CDF73 @ Changed 2020.06.18
+ str r1, [r0]
+ ldr r0, =0x1e78503c @ restore normal mask setting
-+ ldr r1, =0x023CD773 @ Changed 2020.07.08
++ ldr r1, =0x023CDF73 @ Changed 2020.07.08
str r1, [r0]
b bypass_first_reset
diff --git a/meta-openbmc-mods/meta-ast2500/recipes-phosphor/configuration/entity-manager/CPC-Baseboard.json b/meta-openbmc-mods/meta-ast2500/recipes-phosphor/configuration/entity-manager/CPC-Baseboard.json
index 44eda0e66..94e7e7daa 100644
--- a/meta-openbmc-mods/meta-ast2500/recipes-phosphor/configuration/entity-manager/CPC-Baseboard.json
+++ b/meta-openbmc-mods/meta-ast2500/recipes-phosphor/configuration/entity-manager/CPC-Baseboard.json
@@ -981,6 +981,30 @@
"Type": "IpmbSensor"
},
{
+ "Address": 190,
+ "Class": "MESensor",
+ "Name": "Host Cpu Utilization",
+ "SensorType": "utilization",
+ "ScaleValue": 0.392,
+ "Type": "IpmbSensor"
+ },
+ {
+ "Address": 191,
+ "Class": "MESensor",
+ "Name": "Host Pci Bandwidth Utilization",
+ "SensorType": "utilization",
+ "ScaleValue": 0.392,
+ "Type": "IpmbSensor"
+ },
+ {
+ "Address": 192,
+ "Class": "MESensor",
+ "Name": "Host Memory Bandwidth Utilization",
+ "SensorType": "utilization",
+ "ScaleValue": 0.392,
+ "Type": "IpmbSensor"
+ },
+ {
"Address": "0x71",
"Bus": 2,
"ChannelNames": [
@@ -1433,7 +1457,7 @@
"Class": "temp",
"FFGainCoefficient": 0.0,
"FFOffCoefficient": 0.0,
- "ICoefficient": -1.0,
+ "ICoefficient": -0.2,
"ILimitMax": 100,
"ILimitMin": 30,
"Inputs": [
@@ -1444,9 +1468,9 @@
"OutLimitMax": 100,
"OutLimitMin": 30,
"Outputs": [],
- "PCoefficient": -0.15,
+ "PCoefficient": -0.1,
"PositiveHysteresis": 0.0,
- "SetPoint": 80.0,
+ "SetPoint": 75.0,
"SlewNeg": -1,
"SlewPos": 0.0,
"Type": "Pid",
@@ -1458,7 +1482,7 @@
"Class": "temp",
"FFGainCoefficient": 0.0,
"FFOffCoefficient": 0.0,
- "ICoefficient": -1.0,
+ "ICoefficient": -0.2,
"ILimitMax": 100,
"ILimitMin": 30,
"Inputs": [
@@ -1469,9 +1493,9 @@
"OutLimitMax": 100,
"OutLimitMin": 30,
"Outputs": [],
- "PCoefficient": -0.15,
+ "PCoefficient": -0.1,
"PositiveHysteresis": 0.0,
- "SetPoint": 80.0,
+ "SetPoint": 75.0,
"SlewNeg": -1,
"SlewPos": 0.0,
"Type": "Pid",
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 12790632e..83e6deabe 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
@@ -2041,7 +2041,7 @@
"Class": "temp",
"FFGainCoefficient": 0.0,
"FFOffCoefficient": 0.0,
- "ICoefficient": -1.0,
+ "ICoefficient": -0.2,
"ILimitMax": 100,
"ILimitMin": 30,
"Inputs": [
@@ -2052,9 +2052,9 @@
"OutLimitMax": 100,
"OutLimitMin": 30,
"Outputs": [],
- "PCoefficient": -0.15,
+ "PCoefficient": -0.1,
"PositiveHysteresis": 0.0,
- "SetPoint": 80.0,
+ "SetPoint": 75.0,
"SlewNeg": -1,
"SlewPos": 0.0,
"Type": "Pid",
@@ -2066,7 +2066,7 @@
"Class": "temp",
"FFGainCoefficient": 0.0,
"FFOffCoefficient": 0.0,
- "ICoefficient": -1.0,
+ "ICoefficient": -2.0,
"ILimitMax": 100,
"ILimitMin": 30,
"Inputs": [
@@ -2077,9 +2077,9 @@
"OutLimitMax": 100,
"OutLimitMin": 30,
"Outputs": [],
- "PCoefficient": -0.15,
+ "PCoefficient": -0.1,
"PositiveHysteresis": 0.0,
- "SetPoint": 80.0,
+ "SetPoint": 75.0,
"SlewNeg": -1,
"SlewPos": 0.0,
"Type": "Pid",
diff --git a/meta-openbmc-mods/meta-ast2500/recipes-phosphor/configuration/entity-manager/WP-Baseboard.json b/meta-openbmc-mods/meta-ast2500/recipes-phosphor/configuration/entity-manager/WP-Baseboard.json
index 7b128099f..573f1aec6 100644
--- a/meta-openbmc-mods/meta-ast2500/recipes-phosphor/configuration/entity-manager/WP-Baseboard.json
+++ b/meta-openbmc-mods/meta-ast2500/recipes-phosphor/configuration/entity-manager/WP-Baseboard.json
@@ -1567,6 +1567,30 @@
"Type": "IpmbSensor"
},
{
+ "Address": 190,
+ "Class": "MESensor",
+ "Name": "Host Cpu Utilization",
+ "SensorType": "utilization",
+ "ScaleValue": 0.392,
+ "Type": "IpmbSensor"
+ },
+ {
+ "Address": 191,
+ "Class": "MESensor",
+ "Name": "Host Pci Bandwidth Utilization",
+ "SensorType": "utilization",
+ "ScaleValue": 0.392,
+ "Type": "IpmbSensor"
+ },
+ {
+ "Address": 192,
+ "Class": "MESensor",
+ "Name": "Host Memory Bandwidth Utilization",
+ "SensorType": "utilization",
+ "ScaleValue": 0.392,
+ "Type": "IpmbSensor"
+ },
+ {
"EthIndex": 0,
"Name": "Dedicated Management NIC",
"Type": "NIC"
@@ -2008,7 +2032,7 @@
"Class": "temp",
"FFGainCoefficient": 0.0,
"FFOffCoefficient": 0.0,
- "ICoefficient": -1.0,
+ "ICoefficient": -0.2,
"ILimitMax": 100,
"ILimitMin": 30,
"Inputs": [
@@ -2019,9 +2043,9 @@
"OutLimitMax": 100,
"OutLimitMin": 30,
"Outputs": [],
- "PCoefficient": -0.15,
+ "PCoefficient": -0.1,
"PositiveHysteresis": 0.0,
- "SetPoint": 80.0,
+ "SetPoint": 75.0,
"SlewNeg": -1,
"SlewPos": 0.0,
"Type": "Pid",
@@ -2033,7 +2057,7 @@
"Class": "temp",
"FFGainCoefficient": 0.0,
"FFOffCoefficient": 0.0,
- "ICoefficient": -1.0,
+ "ICoefficient": -0.2,
"ILimitMax": 100,
"ILimitMin": 30,
"Inputs": [
@@ -2044,9 +2068,9 @@
"OutLimitMax": 100,
"OutLimitMin": 30,
"Outputs": [],
- "PCoefficient": -0.15,
+ "PCoefficient": -0.1,
"PositiveHysteresis": 0.0,
- "SetPoint": 80.0,
+ "SetPoint": 75.0,
"SlewNeg": -1,
"SlewPos": 0.0,
"Type": "Pid",
diff --git a/meta-openbmc-mods/meta-ast2600/recipes-bsp/u-boot/files/0019-Apply-WDT-reset-mask-to-reset-needed-controller.patch b/meta-openbmc-mods/meta-ast2600/recipes-bsp/u-boot/files/0019-Apply-WDT-reset-mask-to-reset-needed-controller.patch
deleted file mode 100644
index b68975c40..000000000
--- a/meta-openbmc-mods/meta-ast2600/recipes-bsp/u-boot/files/0019-Apply-WDT-reset-mask-to-reset-needed-controller.patch
+++ /dev/null
@@ -1,78 +0,0 @@
-From 5179bc2cba159b9167fee90a2c6a7ea2824df8ad Mon Sep 17 00:00:00 2001
-From: Suryakanth Sekar <suryakanth.sekar@linux.intel.com>
-Date: Thu, 18 Jun 2020 05:32:48 +0530
-Subject: [PATCH] Apply WDT reset mask to reset needed controller
-
-Issue:
-Whenever BIOS and BMC warm reset happens at a time.
-BIOS is not booting.
-
-Root caused:
-BMC resetting the LPC controller during BMC warm reset.
-Which cause BIOS hang as BIOS cannot dump the BIOS serial data.
-
-Fix:
-WDT reset mask has been updated from default to proper value,
-such that controllers interacting with host will not be reset
-during wdt reset operation.
-This was missed earlier, causing BIOS to hang whenever BMC resets,
-as BIOS was accessing the serial port (LPC controller).
-De-coupling LPC controller will make sure BIOS serial port access
-is not disturbed.
-Reset mask is updated not to reset the following controllers
-additionally on the default mask setting.
-1. LPC controller
-2. PWM controller
-3. GPIO controller
-
-Quick Step to reproduce:
-Stop the BMC in uboot and add below bootcmd command
-setenv bootcmd "reset"
-Do the System power ON or System warm reset.
-
-Tested:
-1. Ran overnight continous BIOS and BMC warm reset on two SUTs.
-
-2. Ran the TestApp which dump the BIOS serial port continously and
-do the BMC reset.
-
-3. Stop the BMC in uboot and add below bootcmd command
-setenv bootcmd "reset"
-Do the System Power ON or System warm reset.
-
-Signed-off-by: Suryakanth Sekar <suryakanth.sekar@linux.intel.com>
-Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
----
- arch/arm/mach-aspeed/ast2600/platform.S | 9 +++++++++
- 1 file changed, 9 insertions(+)
-
-diff --git a/arch/arm/mach-aspeed/ast2600/platform.S b/arch/arm/mach-aspeed/ast2600/platform.S
-index d881ba8565f2..68eb0000922a 100644
---- a/arch/arm/mach-aspeed/ast2600/platform.S
-+++ b/arch/arm/mach-aspeed/ast2600/platform.S
-@@ -66,6 +66,9 @@
- #define AST_MAC2_BASE (0x1E680000)
- #define AST_MAC2_CTRL2 (AST_MAC2_BASE + 0x058)
-
-+#define AST_WDT1_BASE 0x1E785000
-+#define AST_WDT1_RESET_MASK2 (AST_WDT1_BASE + 0x020)
-+
- #define AST_GPIO_BASE (0x1E780000)
- #define AST_GPIOYZ_DATA_VALUE (AST_GPIO_BASE + 0x1E0)
-
-@@ -264,6 +267,12 @@ wait_lock:
- str r1, [r0]
-
- 1:
-+ /* disable LPC, PWM and GPIO2 resets on WDT1 reset */
-+ ldr r0, =AST_WDT1_RESET_MASK2
-+ ldr r1, [r0]
-+ bic r1, #0x2A00
-+ str r1, [r0]
-+
- /* release display port reset */
- ldr r0, =AST_SCU_SYSRST_CTRL_CLR
- movw r1, #0x0000
---
-2.7.4
-
diff --git a/meta-openbmc-mods/meta-ast2600/recipes-bsp/u-boot/files/0019-Apply-WDT1-2-reset-mask-to-reset-needed-controller.patch b/meta-openbmc-mods/meta-ast2600/recipes-bsp/u-boot/files/0019-Apply-WDT1-2-reset-mask-to-reset-needed-controller.patch
new file mode 100644
index 000000000..e7af35ff8
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2600/recipes-bsp/u-boot/files/0019-Apply-WDT1-2-reset-mask-to-reset-needed-controller.patch
@@ -0,0 +1,98 @@
+From fa401cd64965d506ddeb94fd47eb694a8f2a3862 Mon Sep 17 00:00:00 2001
+From: Suryakanth Sekar <suryakanth.sekar@linux.intel.com>
+Date: Thu, 18 Jun 2020 05:32:48 +0530
+Subject: [PATCH] Apply WDT1-2 reset mask to reset needed controller
+
+Issue:
+BMC reset during BIOS serial port access causes BIOS hang.
+
+Root caused:
+BMC resetting the LPC controller during BMC warm reset.
+Which cause BIOS hang as BIOS cannot dump the BIOS serial data.
+
+Fix:
+WDT reset mask has been updated from default to proper value,
+such that controllers interacting with host will not be reset
+during wdt reset operation.
+This was missed earlier, causing BIOS to hang whenever BMC resets,
+as BIOS was accessing the serial port (LPC controller).
+De-coupling LPC controller will make sure BIOS serial port access
+is not disturbed.
+And also Reset mask is updated not to reset the following
+additionally on the default mask setting.
+1. LPC controller
+2. PWM controller
+
+Quick Step to reproduce:
+ Stop the BMC in uboot and add below bootcmd command
+ setenv bootcmd "reset"
+ Do the System power ON or System warm reset.
+
+ For WDT2:
+ boot the BMC and ran the /usr/bin/watch_dog_reset.sh
+ Do the System Power ON or System warm reset.
+
+Tested:
+ 1. Ran overnight continous BIOS and BMC warm reset on two SUTs.
+
+ 2.Ran the TestApp which dump the BIOS serial port continously and
+ do the BMC reset.
+
+ 3.Stop the BMC in uboot and add below bootcmd command
+ setenv bootcmd "reset"
+ Do the System Power ON or System warm reset.
+
+ 4.Ran Over night AC cycle test. Completed +1000 in two systems.
+
+ 5.Stopped at u-boot.
+ Issue protect off all command
+ Issue erase all command.
+ BMC should not hang and able to complete the "erase all" command
+
+Signed-off-by: Suryakanth Sekar <suryakanth.sekar@linux.intel.com>
+Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@linux.intel.com>
+---
+ arch/arm/mach-aspeed/ast2600/platform.S | 20 ++++++++++++++++++++
+ 1 file changed, 20 insertions(+)
+
+diff --git a/arch/arm/mach-aspeed/ast2600/platform.S b/arch/arm/mach-aspeed/ast2600/platform.S
+index d881ba8565f2..c77640138653 100644
+--- a/arch/arm/mach-aspeed/ast2600/platform.S
++++ b/arch/arm/mach-aspeed/ast2600/platform.S
+@@ -66,6 +66,14 @@
+ #define AST_MAC2_BASE (0x1E680000)
+ #define AST_MAC2_CTRL2 (AST_MAC2_BASE + 0x058)
+
++#define AST_WDT1_BASE 0x1E785000
++#define AST_WDT1_RESET_MASK1 (AST_WDT1_BASE + 0x01C)
++#define AST_WDT1_RESET_MASK2 (AST_WDT1_BASE + 0x020)
++
++#define AST_WDT2_BASE 0x1E785040
++#define AST_WDT2_RESET_MASK1 (AST_WDT2_BASE + 0x01C)
++#define AST_WDT2_RESET_MASK2 (AST_WDT2_BASE + 0x020)
++
+ #define AST_GPIO_BASE (0x1E780000)
+ #define AST_GPIOYZ_DATA_VALUE (AST_GPIO_BASE + 0x1E0)
+
+@@ -264,6 +272,18 @@ wait_lock:
+ str r1, [r0]
+
+ 1:
++ /* disable LPC and PWM resets on WDT1 reset */
++ ldr r0, =AST_WDT1_RESET_MASK2
++ ldr r1, [r0]
++ bic r1, #0x2800
++ str r1, [r0]
++
++ /* disable LPC and PWM resets on WDT2 reset */
++ ldr r0, =AST_WDT2_RESET_MASK2
++ ldr r1, [r0]
++ bic r1, #0x2800
++ str r1, [r0]
++
+ /* release display port reset */
+ ldr r0, =AST_SCU_SYSRST_CTRL_CLR
+ movw r1, #0x0000
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-ast2600/recipes-bsp/u-boot/u-boot-aspeed-sdk_%.bbappend b/meta-openbmc-mods/meta-ast2600/recipes-bsp/u-boot/u-boot-aspeed-sdk_%.bbappend
index ce22b2057..c2cf07ab3 100644
--- a/meta-openbmc-mods/meta-ast2600/recipes-bsp/u-boot/u-boot-aspeed-sdk_%.bbappend
+++ b/meta-openbmc-mods/meta-ast2600/recipes-bsp/u-boot/u-boot-aspeed-sdk_%.bbappend
@@ -25,7 +25,7 @@ SRC_URI_append_intel-ast2600 = " \
file://0016-Add-system-reset-status-support.patch \
file://0017-Manufacturing-mode-physical-presence-detection.patch \
file://0018-Add-a-workaround-to-cover-VGA-memory-size-bug-in-A0.patch \
- file://0019-Apply-WDT-reset-mask-to-reset-needed-controller.patch \
+ file://0019-Apply-WDT1-2-reset-mask-to-reset-needed-controller.patch \
file://0020-Add-BMC-running-indicator-LED-control.patch \
file://0022-Reboot-into-UBOOT-on-Watchdog-Failures.patch \
"
diff --git a/meta-openbmc-mods/meta-ast2600/recipes-phosphor/configuration/entity-manager/AC-Baseboard.json b/meta-openbmc-mods/meta-ast2600/recipes-phosphor/configuration/entity-manager/AC-Baseboard.json
index add4ca372..0ec6c3611 100644
--- a/meta-openbmc-mods/meta-ast2600/recipes-phosphor/configuration/entity-manager/AC-Baseboard.json
+++ b/meta-openbmc-mods/meta-ast2600/recipes-phosphor/configuration/entity-manager/AC-Baseboard.json
@@ -616,20 +616,6 @@
"Type": "FanRedundancy"
},
{
- "Direction": "Input",
- "Index": 214,
- "Name": "SMI Input",
- "Polarity": "High",
- "Type": "Gpio"
- },
- {
- "Direction": "Input",
- "Index": 218,
- "Name": "ID Button",
- "Polarity": "Low",
- "Type": "Gpio"
- },
- {
"Name": "System Fan connector 1",
"Pwm": 0,
"Tachs": [
diff --git a/meta-openbmc-mods/meta-common/classes/image_types_intel_pfr.bbclass b/meta-openbmc-mods/meta-common/classes/image_types_intel_pfr.bbclass
index e961ae463..2161cdf8d 100644
--- a/meta-openbmc-mods/meta-common/classes/image_types_intel_pfr.bbclass
+++ b/meta-openbmc-mods/meta-common/classes/image_types_intel_pfr.bbclass
@@ -32,58 +32,89 @@ RC_IMAGE_OFFSET = "0x02a00000"
# RC_IMAGE_PAGE= 0x02a00000/1024 = 0xA800 or 43008
RC_IMAGE_PAGE = "43008"
-do_image_pfr () {
- bbplain "Generating Intel PFR compliant BMC image"
-
- bbplain "Build Version = ${build_version}"
- bbplain "Build Number = ${build_number}"
- bbplain "Build Hash = ${build_hash}"
- bbplain "Build SHA = ${SHA_NAME}"
-
- mkdir -p "${PFR_IMAGES_DIR}"
- cd "${PFR_IMAGES_DIR}"
-
- # python script that does the creating PFM, BMC compressed and unsigned images from BMC 128MB raw binary file.
- ${PFR_SCRIPT_DIR}/pfr_image.py ${PFR_CFG_DIR}/pfr_manifest.json ${DEPLOY_DIR_IMAGE}/image-mtd ${build_version} ${build_number} ${build_hash} ${SHA}
+do_image_pfr_internal () {
+ local manifest_json="pfr_manifest${bld_suffix}.json"
+ local pfmconfig_xml="pfm_config${bld_suffix}.xml"
+ local bmcconfig_xml="bmc_config${bld_suffix}.xml"
+ local pfm_signed_bin="pfm_signed${bld_suffix}.bin"
+ local signed_cap_bin="bmc_signedcap${bld_suffix}.bin"
+ local unsigned_cap_bin="bmc_unsigned_cap${bld_suffix}.bin"
+ local unsigned_cap_align_bin="bmc_unsigned_cap${bld_suffix}.bin_aligned"
+ local output_bin="image-mtd-pfr${bld_suffix}"
+
+ # python script that does creating PFM & BMC unsigned, compressed image (from BMC 128MB raw binary file).
+ ${PFR_SCRIPT_DIR}/pfr_image.py -m ${PFR_CFG_DIR}/${manifest_json} -i ${DEPLOY_DIR_IMAGE}/image-mtd -n ${build_version} -b ${build_number} \
+ -h ${build_hash} -s ${SHA} -o ${output_bin}
# sign the PFM region
- ${PFR_SCRIPT_DIR}/blocksign -c ${PFR_CFG_DIR}/pfm_config.xml -o ${PFR_IMAGES_DIR}/pfm_signed.bin ${PFR_IMAGES_DIR}/pfm.bin -v
+ ${PFR_SCRIPT_DIR}/blocksign -c ${PFR_CFG_DIR}/${pfmconfig_xml} -o ${PFR_IMAGES_DIR}/${pfm_signed_bin} ${PFR_IMAGES_DIR}/pfm.bin -v
# Add the signed PFM to rom image
- dd bs=1k conv=notrunc seek=${PFM_OFFSET_PAGE} if=${PFR_IMAGES_DIR}/pfm_signed.bin of=${PFR_IMAGES_DIR}/image-mtd-pfr
+ dd bs=1k conv=notrunc seek=${PFM_OFFSET_PAGE} if=${PFR_IMAGES_DIR}/${pfm_signed_bin} of=${PFR_IMAGES_DIR}/${output_bin}
# Create unsigned BMC update capsule - append with 1. pfm_signed, 2. pbc, 3. bmc compressed
- dd if=${PFR_IMAGES_DIR}/pfm_signed.bin bs=1k >> ${PFR_IMAGES_DIR}/bmc_unsigned_cap.bin
+ dd if=${PFR_IMAGES_DIR}/${pfm_signed_bin} bs=1k >> ${PFR_IMAGES_DIR}/${unsigned_cap_bin}
- dd if=${PFR_IMAGES_DIR}/pbc.bin bs=1k >> ${PFR_IMAGES_DIR}/bmc_unsigned_cap.bin
+ dd if=${PFR_IMAGES_DIR}/pbc.bin bs=1k >> ${PFR_IMAGES_DIR}/${unsigned_cap_bin}
- dd if=${PFR_IMAGES_DIR}/bmc_compressed.bin bs=1k >> ${PFR_IMAGES_DIR}/bmc_unsigned_cap.bin
+ dd if=${PFR_IMAGES_DIR}/bmc_compressed.bin bs=1k >> ${PFR_IMAGES_DIR}/${unsigned_cap_bin}
# Sign the BMC update capsule
- ${PFR_SCRIPT_DIR}/blocksign -c ${PFR_CFG_DIR}/bmc_config.xml -o ${PFR_IMAGES_DIR}/bmc_signed_cap.bin ${PFR_IMAGES_DIR}/bmc_unsigned_cap.bin -v
+ ${PFR_SCRIPT_DIR}/blocksign -c ${PFR_CFG_DIR}/${bmcconfig_xml} -o ${PFR_IMAGES_DIR}/${signed_cap_bin} ${PFR_IMAGES_DIR}/${unsigned_cap_bin} -v
# Add the signed bmc update capsule to full rom image @ 0x2a00000
- dd bs=1k conv=notrunc seek=${RC_IMAGE_PAGE} if=${PFR_IMAGES_DIR}/bmc_signed_cap.bin of=${PFR_IMAGES_DIR}/image-mtd-pfr
-
- # Append date and time to all the PFR images
- mv ${PFR_IMAGES_DIR}/pfm_signed.bin ${PFR_IMAGES_DIR}/pfm_signed-${DATETIME}.bin
- mv ${PFR_IMAGES_DIR}/pfm.bin ${PFR_IMAGES_DIR}/pfm-${DATETIME}.bin
- mv ${PFR_IMAGES_DIR}/pbc.bin ${PFR_IMAGES_DIR}/pbc-${DATETIME}.bin
- mv ${PFR_IMAGES_DIR}/bmc_compressed.bin ${PFR_IMAGES_DIR}/bmc_compressed-${DATETIME}.bin
- mv ${PFR_IMAGES_DIR}/bmc_unsigned_cap.bin ${PFR_IMAGES_DIR}/bmc_unsigned_cap-${DATETIME}.bin
- mv ${PFR_IMAGES_DIR}/bmc_signed_cap.bin ${PFR_IMAGES_DIR}/bmc_signed_cap-${DATETIME}.bin
- mv ${PFR_IMAGES_DIR}/image-mtd-pfr ${PFR_IMAGES_DIR}/image-mtd-pfr-${DATETIME}.bin
+ dd bs=1k conv=notrunc seek=${RC_IMAGE_PAGE} if=${PFR_IMAGES_DIR}/${signed_cap_bin} of=${PFR_IMAGES_DIR}/${output_bin}
+
+ # Rename all PFR output images by appending date and time, so that they don't meddle with subsequent call to this function.
+ mv ${PFR_IMAGES_DIR}/${pfm_signed_bin} ${PFR_IMAGES_DIR}/pfm_signed${bld_suffix}-${DATETIME}.bin
+ mv ${PFR_IMAGES_DIR}/${unsigned_cap_bin} ${PFR_IMAGES_DIR}/bmc_unsigned_cap${bld_suffix}-${DATETIME}.bin
+ mv ${PFR_IMAGES_DIR}/${unsigned_cap_align_bin} ${PFR_IMAGES_DIR}/bmc_unsigned_cap${bld_suffix}-${DATETIME}.bin_aligned
+ mv ${PFR_IMAGES_DIR}/${signed_cap_bin} ${PFR_IMAGES_DIR}/bmc_signed_cap${bld_suffix}-${DATETIME}.bin
+ mv ${PFR_IMAGES_DIR}/${output_bin} ${PFR_IMAGES_DIR}/image-mtd-pfr${bld_suffix}-${DATETIME}.bin
+ # Append date and time to all 'pfr_image.py' output binaries.
+ mv ${PFR_IMAGES_DIR}/pfm.bin ${PFR_IMAGES_DIR}/pfm${bld_suffix}-${DATETIME}.bin
+ mv ${PFR_IMAGES_DIR}/pfm.bin_aligned ${PFR_IMAGES_DIR}/pfm${bld_suffix}-${DATETIME}.bin_aligned
+ mv ${PFR_IMAGES_DIR}/pbc.bin ${PFR_IMAGES_DIR}/pbc${bld_suffix}-${DATETIME}.bin
+ mv ${PFR_IMAGES_DIR}/bmc_compressed.bin ${PFR_IMAGES_DIR}/bmc_compressed${bld_suffix}-${DATETIME}.bin
# Use relative links. The build process removes some of the build
# artifacts and that makes fully qualified pathes break. Relative links
# work because of the 'cd "${PFR_IMAGES_DIR}"' at the start of this section.
- ln -sf image-mtd-pfr-${DATETIME}.bin ${PFR_IMAGES_DIR}/image-mtd-pfr.bin
- ln -sf image-mtd-pfr-${DATETIME}.bin ${PFR_IMAGES_DIR}/OBMC-${@ do_get_version(d)}-pfr-full.ROM
- ln -sf bmc_signed_cap-${DATETIME}.bin ${PFR_IMAGES_DIR}/bmc_signed_cap.bin
- ln -sf bmc_signed_cap-${DATETIME}.bin ${PFR_IMAGES_DIR}/OBMC-${@ do_get_version(d)}-pfr-oob.bin
+ ln -sf image-mtd-pfr${bld_suffix}-${DATETIME}.bin ${PFR_IMAGES_DIR}/image-mtd-pfr${bld_suffix}.bin
+ ln -sf image-mtd-pfr${bld_suffix}-${DATETIME}.bin ${PFR_IMAGES_DIR}/OBMC${bld_suffix}-${@ do_get_version(d)}-pfr-full.ROM
+ ln -sf bmc_signed_cap${bld_suffix}-${DATETIME}.bin ${PFR_IMAGES_DIR}/bmc_signed_cap${bld_suffix}.bin
+ ln -sf bmc_signed_cap${bld_suffix}-${DATETIME}.bin ${PFR_IMAGES_DIR}/OBMC${bld_suffix}-${@ do_get_version(d)}-pfr-oob.bin
+}
+
+do_image_pfr () {
+ # PFR image, additional build components information suffix.
+ local bld_suffix=""
+
+ bbplain "Generating Intel PFR compliant BMC image for '${PRODUCT_GENERATION}'"
+
+ bbplain "Build Version = ${build_version}"
+ bbplain "Build Number = ${build_number}"
+ bbplain "Build Hash = ${build_hash}"
+ bbplain "Build SHA = ${SHA_NAME}"
+
+ mkdir -p "${PFR_IMAGES_DIR}"
+ cd "${PFR_IMAGES_DIR}"
+
+ # First, Build default image.
+ bld_suffix=""
+ do_image_pfr_internal
+
+ if [ ${PRODUCT_GENERATION} = "wht" ]; then
+ #Build additional component images also, for whitley generation, if needed.
+ if ! [ -z ${BUILD_SEGD} ] && [ ${BUILD_SEGD} = "yes" ]; then
+ bld_suffix="_d"
+ do_image_pfr_internal
+ fi
+ fi
}
-do_image_pfr[vardepsexclude] += "DATE DATETIME"
+# Include 'do_image_pfr_internal' in 'vardepsexclude';Else Taskhash mismatch error will occur.
+do_image_pfr[vardepsexclude] += "do_image_pfr_internal DATE DATETIME BUILD_SEGD"
do_image_pfr[vardeps] += "IPMI_MAJOR IPMI_MINOR IPMI_AUX13 IPMI_AUX14 IPMI_AUX15 IPMI_AUX16"
do_image_pfr[depends] += " \
obmc-intel-pfr-image-native:do_populate_sysroot \
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 184f6c0f1..1a1a83dce 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.65"
+SRCREV = "wht-0.9"
S = "${WORKDIR}/git"
diff --git a/meta-openbmc-mods/meta-common/recipes-core/interfaces/libmctp_git.bb b/meta-openbmc-mods/meta-common/recipes-core/interfaces/libmctp_git.bb
index 170fbdff9..093419202 100644
--- a/meta-openbmc-mods/meta-common/recipes-core/interfaces/libmctp_git.bb
+++ b/meta-openbmc-mods/meta-common/recipes-core/interfaces/libmctp_git.bb
@@ -2,7 +2,7 @@ SUMMARY = "libmctp"
DESCRIPTION = "Implementation of MCTP (DTMF DSP0236)"
SRC_URI = "git://github.com/openbmc/libmctp.git"
-SRCREV = "3ac70d62571953be172a0d16976e383490d25059"
+SRCREV = "96d5449211228c141b65dbe60a121c23f6c79cfb"
PV = "0.1+git${SRCPV}"
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 13171277b..cd2011b4a 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
@@ -2,4 +2,4 @@ EXTRA_OECMAKE += "${@bb.utils.contains('IMAGE_FSTYPES', 'intel-pfr', '-DINTEL_PF
EXTRA_OECMAKE += "${@bb.utils.contains('EXTRA_IMAGE_FEATURES', 'validation-unsecure', '-DBMC_VALIDATION_UNSECURE_FEATURE=ON', '', d)}"
EXTRA_OECMAKE += "-DUSING_ENTITY_MANAGER_DECORATORS=OFF"
SRC_URI = "git://github.com/openbmc/intel-ipmi-oem.git"
-SRCREV = "2030d7c8ebb6ccdbc300bf4967647a3b496c9726"
+SRCREV = "04a38ed10db3a0203aa7804bfea6fbd69dafdde8"
diff --git a/meta-openbmc-mods/meta-common/recipes-extended/sdbusplus/sdbusplus/0001-sdbusplus-settable-timeout-value-for-async_method_ca.patch b/meta-openbmc-mods/meta-common/recipes-extended/sdbusplus/sdbusplus/0001-sdbusplus-settable-timeout-value-for-async_method_ca.patch
new file mode 100644
index 000000000..82d39cea5
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-extended/sdbusplus/sdbusplus/0001-sdbusplus-settable-timeout-value-for-async_method_ca.patch
@@ -0,0 +1,134 @@
+From 42040cbbc6c6691cef3bee4e42808c3921be9766 Mon Sep 17 00:00:00 2001
+From: Konrad Sztyber <konrad.sztyber@intel.com>
+Date: Fri, 27 Mar 2020 16:48:26 +0100
+Subject: [PATCH] sdbusplus: settable timeout value for async_method_call
+
+Added extra method, asio::connection::async_method_call_timed allowing
+the user to specify the value of the timeout to be used for that call
+(in microseconds). Using 0 as the timeout results in using the default
+value, which is equivalent to calling asio::connection::async_method_call.
+
+Signed-off-by: Konrad Sztyber <konrad.sztyber@intel.com>
+Change-Id: Id79772e46a77f62af5b39ec341648e34af6aaf99
+---
+ sdbusplus/asio/connection.hpp | 51 +++++++++++++++++---
+ sdbusplus/asio/detail/async_send_handler.hpp | 7 ++-
+ 2 files changed, 46 insertions(+), 12 deletions(-)
+
+diff --git a/sdbusplus/asio/connection.hpp b/sdbusplus/asio/connection.hpp
+index b3ff4fd..ec07e4e 100644
+--- a/sdbusplus/asio/connection.hpp
++++ b/sdbusplus/asio/connection.hpp
+@@ -84,7 +84,8 @@ class connection : public sdbusplus::bus::bus
+ inline BOOST_ASIO_INITFN_RESULT_TYPE(MessageHandler,
+ void(boost::system::error_code,
+ message::message&))
+- async_send(message::message& m, MessageHandler&& handler)
++ async_send(message::message& m, MessageHandler&& handler,
++ uint64_t timeout = 0)
+ {
+ boost::asio::async_completion<
+ MessageHandler, void(boost::system::error_code, message::message)>
+@@ -92,12 +93,12 @@ class connection : public sdbusplus::bus::bus
+ detail::async_send_handler<typename boost::asio::async_result<
+ MessageHandler, void(boost::system::error_code,
+ message::message)>::completion_handler_type>(
+- std::move(init.completion_handler))(get(), m);
++ std::move(init.completion_handler))(get(), m, timeout);
+ return init.result.get();
+ }
+
+ /** @brief Perform an asynchronous method call, with input parameter packing
+- * and return value unpacking
++ * and return value unpacking.
+ *
+ * @param[in] handler - A function object that is to be called as a
+ * continuation for the async dbus method call. The
+@@ -108,6 +109,8 @@ class connection : public sdbusplus::bus::bus
+ * @param[in] objpath - The object's path for the call.
+ * @param[in] interf - The object's interface to call.
+ * @param[in] method - The object's method to call.
++ * @param[in] timeout - The timeout for the method call in usec (0 results
++ * in using the default value).
+ * @param[in] a... - Optional parameters for the method call.
+ *
+ * @return immediate return of the internal handler registration. The
+@@ -116,10 +119,12 @@ class connection : public sdbusplus::bus::bus
+ * complete.
+ */
+ template <typename MessageHandler, typename... InputArgs>
+- void async_method_call(MessageHandler&& handler, const std::string& service,
+- const std::string& objpath,
+- const std::string& interf, const std::string& method,
+- const InputArgs&... a)
++ void async_method_call_timed(MessageHandler&& handler,
++ const std::string& service,
++ const std::string& objpath,
++ const std::string& interf,
++ const std::string& method, uint64_t timeout,
++ const InputArgs&... a)
+ {
+ using FunctionTuple = boost::callable_traits::args_t<MessageHandler>;
+ using FunctionTupleType =
+@@ -184,7 +189,37 @@ class connection : public sdbusplus::bus::bus
+ applyHandler(ec, m);
+ return;
+ }
+- async_send(m, std::forward<decltype(applyHandler)>(applyHandler));
++ async_send(m, std::forward<decltype(applyHandler)>(applyHandler),
++ timeout);
++ }
++
++ /** @brief Perform an asynchronous method call, with input parameter packing
++ * and return value unpacking. Uses the default timeout value.
++ *
++ * @param[in] handler - A function object that is to be called as a
++ * continuation for the async dbus method call. The
++ * arguments to parse on the return are deduced from
++ * the handler's signature and then passed in along
++ * with an error code and optional message::message
++ * @param[in] service - The service to call.
++ * @param[in] objpath - The object's path for the call.
++ * @param[in] interf - The object's interface to call.
++ * @param[in] method - The object's method to call.
++ * @param[in] a... - Optional parameters for the method call.
++ *
++ * @return immediate return of the internal handler registration. The
++ * result of the actual asynchronous call will get unpacked from
++ * the message and passed into the handler when the call is
++ * complete.
++ */
++ template <typename MessageHandler, typename... InputArgs>
++ void async_method_call(MessageHandler&& handler, const std::string& service,
++ const std::string& objpath,
++ const std::string& interf, const std::string& method,
++ const InputArgs&... a)
++ {
++ async_method_call_timed(std::forward<MessageHandler>(handler), service,
++ objpath, interf, method, 0, a...);
+ }
+
+ /** @brief Perform a yielding asynchronous method call, with input
+diff --git a/sdbusplus/asio/detail/async_send_handler.hpp b/sdbusplus/asio/detail/async_send_handler.hpp
+index bb896ad..cb91f51 100644
+--- a/sdbusplus/asio/detail/async_send_handler.hpp
++++ b/sdbusplus/asio/detail/async_send_handler.hpp
+@@ -35,12 +35,11 @@ struct async_send_handler
+ {}
+ async_send_handler(Handler& handler) : handler_(handler)
+ {}
+- void operator()(sd_bus* conn, message::message& mesg)
++ void operator()(sd_bus* conn, message::message& mesg, uint64_t timeout)
+ {
+ async_send_handler* context = new async_send_handler(std::move(*this));
+- // 0 is the default timeout
+- int ec =
+- sd_bus_call_async(conn, NULL, mesg.get(), &callback, context, 0);
++ int ec = sd_bus_call_async(conn, NULL, mesg.get(), &callback, context,
++ timeout);
+ if (ec < 0)
+ {
+ // add a deleter to context because handler may throw
+--
+2.25.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-extended/sdbusplus/sdbusplus/0002-sdbusplus_Add_new_signal_and_extend_set_property_methods.patch b/meta-openbmc-mods/meta-common/recipes-extended/sdbusplus/sdbusplus/0002-sdbusplus_Add_new_signal_and_extend_set_property_methods.patch
new file mode 100644
index 000000000..21c5b3afa
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-extended/sdbusplus/sdbusplus/0002-sdbusplus_Add_new_signal_and_extend_set_property_methods.patch
@@ -0,0 +1,78 @@
+From 9589a690577bdb4d2b79894d1c6a9c8396af5c2a Mon Sep 17 00:00:00 2001
+From: Zhikui Ren <zhikui.ren@intel.com>
+Date: Fri, 26 Jun 2020 17:42:47 -0700
+Subject: [PATCH] Add new_signal and extend set_property methods to
+ dbus_interface
+
+new_signal exports the same member function of sdbusplus::server::interface
+
+extend set_property to be able to return true only when the property value
+is changed. default behavior remains unchanged - returns true when property
+is updated successfully, value may be same or changed.
+
+With these two functions, dbus_interface can broadcast new signal when
+a property is changed. This allows a customized message to be sent
+when a property changes.
+
+Tested:
+Build test code to use the two new method to create and send new_signal when
+a property is changed.
+
+Signed-off-by: Zhikui Ren <zhikui.ren@intel.com>
+Change-Id: I1815885bc77aad2c526b402f1386d4914479e738
+
+%% original patch: 0002-sdbusplus_Add_new_signal_and_extend_set_property_methods.patch
+---
+ sdbusplus/asio/object_server.hpp | 21 +++++++++++++++++++--
+ 1 file changed, 19 insertions(+), 2 deletions(-)
+
+diff --git a/sdbusplus/asio/object_server.hpp b/sdbusplus/asio/object_server.hpp
+index 7a3e8e7..35199bc 100644
+--- a/sdbusplus/asio/object_server.hpp
++++ b/sdbusplus/asio/object_server.hpp
+@@ -494,7 +494,7 @@ class dbus_interface
+
+ return true;
+ }
+- template <typename PropertyType>
++ template <typename PropertyType, bool changesOnly = false>
+ bool set_property(const std::string& name, const PropertyType& value)
+ {
+ if (!initialized_)
+@@ -511,8 +511,12 @@ class dbus_interface
+ if (status != SetPropertyReturnValue::sameValueUpdated)
+ {
+ signal_property(name);
++ return true;
++ }
++ if constexpr (!changesOnly)
++ {
++ return true;
+ }
+- return true;
+ }
+ }
+ return false;
+@@ -720,6 +724,19 @@ class dbus_interface
+ return sd_bus_error_set_const(error, SD_BUS_ERROR_INVALID_ARGS, NULL);
+ }
+
++ /** @brief Create a new signal message.
++ *
++ * @param[in] member - The signal name to create.
++ */
++ auto new_signal(const char* member)
++ {
++ if (!initialized_)
++ {
++ return message::message(nullptr);
++ }
++ return interface_->new_signal(member);
++ }
++
+ bool initialize(const bool skipPropertyChangedSignal = false)
+ {
+ // can only register once
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-extended/sdbusplus/sdbusplus_%.bbappend b/meta-openbmc-mods/meta-common/recipes-extended/sdbusplus/sdbusplus_%.bbappend
new file mode 100644
index 000000000..c0b530840
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-extended/sdbusplus/sdbusplus_%.bbappend
@@ -0,0 +1,6 @@
+FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
+
+SRC_URI += " \
+ file://0001-sdbusplus-settable-timeout-value-for-async_method_ca.patch \
+ file://0002-sdbusplus_Add_new_signal_and_extend_set_property_methods.patch \
+ "
diff --git a/meta-openbmc-mods/meta-common/recipes-graphics/libvncserver/libvncserver_%.bbappend b/meta-openbmc-mods/meta-common/recipes-graphics/libvncserver/libvncserver_%.bbappend
index d25bb7753..6df8f5a89 100644
--- a/meta-openbmc-mods/meta-common/recipes-graphics/libvncserver/libvncserver_%.bbappend
+++ b/meta-openbmc-mods/meta-common/recipes-graphics/libvncserver/libvncserver_%.bbappend
@@ -2,4 +2,4 @@ FILESEXTRAPATHS_append := ":${THISDIR}/${PN}"
# Use the latest to support obmc-ikvm properly
SRC_URI = "git://github.com/LibVNC/libvncserver"
-SRCREV = "38fd347afb6e2b720fdc0dc43bb3e5f179d0ce4e"
+SRCREV = "b7195ce95c27255c14382bdc270b2972a7f9347b"
diff --git a/meta-openbmc-mods/meta-common/recipes-graphics/obmc-ikvm/obmc-ikvm/0004-Connect-HID-gadget-device-dynamically.patch b/meta-openbmc-mods/meta-common/recipes-graphics/obmc-ikvm/obmc-ikvm/0004-Connect-HID-gadget-device-dynamically.patch
new file mode 100644
index 000000000..0fe93c604
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-graphics/obmc-ikvm/obmc-ikvm/0004-Connect-HID-gadget-device-dynamically.patch
@@ -0,0 +1,494 @@
+From 9a0f78ab773b33fd0445b23358097ddcd175a58f Mon Sep 17 00:00:00 2001
+From: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+Date: Wed, 22 Jul 2020 23:39:18 -0700
+Subject: [PATCH] Connect HID gadget device dynamically
+
+Connecting HID gadget device statically from the beginning of this
+service causes an issue on WHLK test. To prevent the issue, this
+commit changes the HID gadget device handling as dynamic so that
+the HID gadget device can be connected when this service has at
+least one KVM client.
+
+Tested: /dev/hidg0 and /dev/hidg1 created only when at least one
+KVM client is connected.
+
+Change-Id: I5f6596b9e4e297fb6b507000499fc041460659f7
+Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+---
+ create_usbhid.sh | 278 ++++++++++++++++++++++++--------------------
+ ikvm_input.cpp | 64 +++++++++-
+ ikvm_input.hpp | 14 +++
+ ikvm_server.cpp | 2 +
+ start-ipkvm.service | 2 +-
+ 5 files changed, 230 insertions(+), 130 deletions(-)
+
+diff --git a/create_usbhid.sh b/create_usbhid.sh
+index 656299102d7f..d1fa4e036bbe 100644
+--- a/create_usbhid.sh
++++ b/create_usbhid.sh
+@@ -1,135 +1,157 @@
+ #!/bin/sh
+
+-new_directory="/sys/kernel/config/usb_gadget/obmc_hid"
++hid_conf_directory="/sys/kernel/config/usb_gadget/obmc_hid"
++dev_name="1e6a0000.usb-vhub"
+
+-if [ -e "${new_directory}" ]; then
+- exit 0
+-fi
++create_hid() {
++ # create gadget
++ mkdir "${hid_conf_directory}"
++ cd "${hid_conf_directory}"
++
++ # add basic information
++ echo 0x0100 > bcdDevice
++ echo 0x0200 > bcdUSB
++ echo 0x0104 > idProduct # Multifunction Composite Gadget
++ echo 0x1d6b > idVendor # Linux Foundation
++
++ # create English locale
++ mkdir strings/0x409
++
++ echo "OpenBMC" > strings/0x409/manufacturer
++ echo "virtual_input" > strings/0x409/product
++ echo "OBMC0001" > strings/0x409/serialnumber
++
++ # Create HID keyboard function
++ mkdir functions/hid.0
++
++ echo 1 > functions/hid.0/protocol # 1: keyboard
++ echo 8 > functions/hid.0/report_length
++ echo 1 > functions/hid.0/subclass
++
++ # Binary HID keyboard descriptor
++ # 0x05, 0x01, // USAGE_PAGE (Generic Desktop)
++ # 0x09, 0x06, // USAGE (Keyboard)
++ # 0xa1, 0x01, // COLLECTION (Application)
++ # 0x05, 0x07, // USAGE_PAGE (Keyboard)
++ # 0x19, 0xe0, // USAGE_MINIMUM (Keyboard LeftControl)
++ # 0x29, 0xe7, // USAGE_MAXIMUM (Keyboard Right GUI)
++ # 0x15, 0x00, // LOGICAL_MINIMUM (0)
++ # 0x25, 0x01, // LOGICAL_MAXIMUM (1)
++ # 0x75, 0x01, // REPORT_SIZE (1)
++ # 0x95, 0x08, // REPORT_COUNT (8)
++ # 0x81, 0x02, // INPUT (Data,Var,Abs)
++ # 0x95, 0x01, // REPORT_COUNT (1)
++ # 0x75, 0x08, // REPORT_SIZE (8)
++ # 0x81, 0x03, // INPUT (Data,Var,Abs)
++ # 0x95, 0x05, // REPORT_COUNT (5)
++ # 0x75, 0x01, // REPORT_SIZE (1)
++ # 0x05, 0x08, // USAGE_PAGE (LEDs)
++ # 0x19, 0x01, // USAGE_MINIMUM (Num Lock)
++ # 0x29, 0x05, // USAGE_MAXIMUM (Kana)
++ # 0x91, 0x02, // OUTPUT (Data,Var,Abs)
++ # 0x95, 0x01, // REPORT_COUNT (1)
++ # 0x75, 0x03, // REPORT_SIZE (3)
++ # 0x91, 0x03, // OUTPUT (Cnst,Var,Abs)
++ # 0x95, 0x06, // REPORT_COUNT (6)
++ # 0x75, 0x08, // REPORT_SIZE (8)
++ # 0x15, 0x00, // LOGICAL_MINIMUM (0)
++ # 0x25, 0x65, // LOGICAL_MAXIMUM (101)
++ # 0x05, 0x07, // USAGE_PAGE (Keyboard)
++ # 0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated))
++ # 0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application)
++ # 0x81, 0x00, // INPUT (Data,Ary,Abs)
++ # 0xc0 // END_COLLECTION
++ echo -ne '\x05\x01\x09\x06\xa1\x01\x05\x07\x19\xe0\x29\xe7\x15\x00\x25\x01\x75\x01\x95\x08\x81\x02\x95\x01\x75\x08\x81\x03\x95\x05\x75\x01\x05\x08\x19\x01\x29\x05\x91\x02\x95\x01\x75\x03\x91\x03\x95\x06\x75\x08\x15\x00\x25\x65\x05\x07\x19\x00\x29\x65\x81\x00\xc0' > functions/hid.0/report_desc
++
++ # Create HID mouse function
++ mkdir functions/hid.1
++
++ echo 2 > functions/hid.1/protocol # 2: mouse
++ echo 5 > functions/hid.1/report_length
++ echo 1 > functions/hid.1/subclass
++
++ # Binary HID mouse descriptor (absolute coordinate)
++ # 0x05, 0x01, // USAGE_PAGE (Generic Desktop)
++ # 0x09, 0x02, // USAGE (Mouse)
++ # 0xa1, 0x01, // COLLECTION (Application)
++ # 0x09, 0x01, // USAGE (Pointer)
++ # 0xa1, 0x00, // COLLECTION (Physical)
++ # 0x05, 0x09, // USAGE_PAGE (Button)
++ # 0x19, 0x01, // USAGE_MINIMUM (Button 1)
++ # 0x29, 0x03, // USAGE_MAXIMUM (Button 3)
++ # 0x15, 0x00, // LOGICAL_MINIMUM (0)
++ # 0x25, 0x01, // LOGICAL_MAXIMUM (1)
++ # 0x95, 0x03, // REPORT_COUNT (3)
++ # 0x75, 0x01, // REPORT_SIZE (1)
++ # 0x81, 0x02, // INPUT (Data,Var,Abs)
++ # 0x95, 0x01, // REPORT_COUNT (1)
++ # 0x75, 0x05, // REPORT_SIZE (5)
++ # 0x81, 0x03, // INPUT (Cnst,Var,Abs)
++ # 0x05, 0x01, // USAGE_PAGE (Generic Desktop)
++ # 0x09, 0x30, // USAGE (X)
++ # 0x09, 0x31, // USAGE (Y)
++ # 0x35, 0x00, // PHYSICAL_MINIMUM (0)
++ # 0x46, 0xff, 0x7f, // PHYSICAL_MAXIMUM (32767)
++ # 0x15, 0x00, // LOGICAL_MINIMUM (0)
++ # 0x26, 0xff, 0x7f, // LOGICAL_MAXIMUM (32767)
++ # 0x65, 0x11, // UNIT (SI Lin:Distance)
++ # 0x55, 0x00, // UNIT_EXPONENT (0)
++ # 0x75, 0x10, // REPORT_SIZE (16)
++ # 0x95, 0x02, // REPORT_COUNT (2)
++ # 0x81, 0x02, // INPUT (Data,Var,Abs)
++ # 0xc0, // END_COLLECTION
++ # 0xc0 // END_COLLECTION
++ echo -ne '\x05\x01\x09\x02\xa1\x01\x09\x01\xa1\x00\x05\x09\x19\x01\x29\x03\x15\x00\x25\x01\x95\x03\x75\x01\x81\x02\x95\x01\x75\x05\x81\x03\x05\x01\x09\x30\x09\x31\x35\x00\x46\xff\x7f\x15\x00\x26\xff\x7f\x65\x11\x55\x00\x75\x10\x95\x02\x81\x02\xc0\xc0' > functions/hid.1/report_desc
++
++ # Create configuration
++ mkdir configs/c.1
++ mkdir configs/c.1/strings/0x409
++
++ echo 0x80 > configs/c.1/bmAttributes
++ echo 200 > configs/c.1/MaxPower
++ echo "" > configs/c.1/strings/0x409/configuration
++
++ # Link HID functions to configuration
++ ln -s functions/hid.0 configs/c.1
++ ln -s functions/hid.1 configs/c.1
++}
++
++connect_hid() {
++ if ! [[ `cat UDC` =~ "${dev_name}:p" ]]; then
++ i=0
++ num_ports=5
++ base_usb_dir="/sys/bus/platform/devices/${dev_name}/${dev_name}:p"
++ while [ $i -lt $num_ports ]; do
++ port=$(($i + 1))
++ i=$port
++ if [ ! -e "${base_usb_dir}${port}/gadget/suspended" ]; then
++ break
++ fi
++ done
++ echo "${dev_name}:p${port}" > UDC
++ fi
++}
++
++disconnect_hid() {
++ if [[ `cat UDC` =~ "${dev_name}:p" ]]; then
++ echo "" > UDC
++ fi
++}
+
+-# create gadget
+ original_directory="$(pwd)"
+-mkdir "${new_directory}"
+-cd "${new_directory}"
+-
+-# add basic information
+-echo 0x0100 > bcdDevice
+-echo 0x0200 > bcdUSB
+-echo 0x0104 > idProduct # Multifunction Composite Gadget
+-echo 0x1d6b > idVendor # Linux Foundation
+-
+-# create English locale
+-mkdir strings/0x409
+-
+-echo "OpenBMC" > strings/0x409/manufacturer
+-echo "virtual_input" > strings/0x409/product
+-echo "OBMC0001" > strings/0x409/serialnumber
+-
+-# Create HID keyboard function
+-mkdir functions/hid.0
+-
+-echo 1 > functions/hid.0/protocol # 1: keyboard
+-echo 8 > functions/hid.0/report_length
+-echo 1 > functions/hid.0/subclass
+-
+-# Binary HID keyboard descriptor
+-# 0x05, 0x01, // USAGE_PAGE (Generic Desktop)
+-# 0x09, 0x06, // USAGE (Keyboard)
+-# 0xa1, 0x01, // COLLECTION (Application)
+-# 0x05, 0x07, // USAGE_PAGE (Keyboard)
+-# 0x19, 0xe0, // USAGE_MINIMUM (Keyboard LeftControl)
+-# 0x29, 0xe7, // USAGE_MAXIMUM (Keyboard Right GUI)
+-# 0x15, 0x00, // LOGICAL_MINIMUM (0)
+-# 0x25, 0x01, // LOGICAL_MAXIMUM (1)
+-# 0x75, 0x01, // REPORT_SIZE (1)
+-# 0x95, 0x08, // REPORT_COUNT (8)
+-# 0x81, 0x02, // INPUT (Data,Var,Abs)
+-# 0x95, 0x01, // REPORT_COUNT (1)
+-# 0x75, 0x08, // REPORT_SIZE (8)
+-# 0x81, 0x03, // INPUT (Data,Var,Abs)
+-# 0x95, 0x05, // REPORT_COUNT (5)
+-# 0x75, 0x01, // REPORT_SIZE (1)
+-# 0x05, 0x08, // USAGE_PAGE (LEDs)
+-# 0x19, 0x01, // USAGE_MINIMUM (Num Lock)
+-# 0x29, 0x05, // USAGE_MAXIMUM (Kana)
+-# 0x91, 0x02, // OUTPUT (Data,Var,Abs)
+-# 0x95, 0x01, // REPORT_COUNT (1)
+-# 0x75, 0x03, // REPORT_SIZE (3)
+-# 0x91, 0x03, // OUTPUT (Cnst,Var,Abs)
+-# 0x95, 0x06, // REPORT_COUNT (6)
+-# 0x75, 0x08, // REPORT_SIZE (8)
+-# 0x15, 0x00, // LOGICAL_MINIMUM (0)
+-# 0x25, 0x65, // LOGICAL_MAXIMUM (101)
+-# 0x05, 0x07, // USAGE_PAGE (Keyboard)
+-# 0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated))
+-# 0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application)
+-# 0x81, 0x00, // INPUT (Data,Ary,Abs)
+-# 0xc0 // END_COLLECTION
+-echo -ne '\x05\x01\x09\x06\xa1\x01\x05\x07\x19\xe0\x29\xe7\x15\x00\x25\x01\x75\x01\x95\x08\x81\x02\x95\x01\x75\x08\x81\x03\x95\x05\x75\x01\x05\x08\x19\x01\x29\x05\x91\x02\x95\x01\x75\x03\x91\x03\x95\x06\x75\x08\x15\x00\x25\x65\x05\x07\x19\x00\x29\x65\x81\x00\xc0' > functions/hid.0/report_desc
+-
+-# Create HID mouse function
+-mkdir functions/hid.1
+-
+-echo 2 > functions/hid.1/protocol # 2: mouse
+-echo 5 > functions/hid.1/report_length
+-echo 1 > functions/hid.1/subclass
+-
+-# Binary HID mouse descriptor (absolute coordinate)
+-# 0x05, 0x01, // USAGE_PAGE (Generic Desktop)
+-# 0x09, 0x02, // USAGE (Mouse)
+-# 0xa1, 0x01, // COLLECTION (Application)
+-# 0x09, 0x01, // USAGE (Pointer)
+-# 0xa1, 0x00, // COLLECTION (Physical)
+-# 0x05, 0x09, // USAGE_PAGE (Button)
+-# 0x19, 0x01, // USAGE_MINIMUM (Button 1)
+-# 0x29, 0x03, // USAGE_MAXIMUM (Button 3)
+-# 0x15, 0x00, // LOGICAL_MINIMUM (0)
+-# 0x25, 0x01, // LOGICAL_MAXIMUM (1)
+-# 0x95, 0x03, // REPORT_COUNT (3)
+-# 0x75, 0x01, // REPORT_SIZE (1)
+-# 0x81, 0x02, // INPUT (Data,Var,Abs)
+-# 0x95, 0x01, // REPORT_COUNT (1)
+-# 0x75, 0x05, // REPORT_SIZE (5)
+-# 0x81, 0x03, // INPUT (Cnst,Var,Abs)
+-# 0x05, 0x01, // USAGE_PAGE (Generic Desktop)
+-# 0x09, 0x30, // USAGE (X)
+-# 0x09, 0x31, // USAGE (Y)
+-# 0x35, 0x00, // PHYSICAL_MINIMUM (0)
+-# 0x46, 0xff, 0x7f, // PHYSICAL_MAXIMUM (32767)
+-# 0x15, 0x00, // LOGICAL_MINIMUM (0)
+-# 0x26, 0xff, 0x7f, // LOGICAL_MAXIMUM (32767)
+-# 0x65, 0x11, // UNIT (SI Lin:Distance)
+-# 0x55, 0x00, // UNIT_EXPONENT (0)
+-# 0x75, 0x10, // REPORT_SIZE (16)
+-# 0x95, 0x02, // REPORT_COUNT (2)
+-# 0x81, 0x02, // INPUT (Data,Var,Abs)
+-# 0xc0, // END_COLLECTION
+-# 0xc0 // END_COLLECTION
+-echo -ne '\x05\x01\x09\x02\xa1\x01\x09\x01\xa1\x00\x05\x09\x19\x01\x29\x03\x15\x00\x25\x01\x95\x03\x75\x01\x81\x02\x95\x01\x75\x05\x81\x03\x05\x01\x09\x30\x09\x31\x35\x00\x46\xff\x7f\x15\x00\x26\xff\x7f\x65\x11\x55\x00\x75\x10\x95\x02\x81\x02\xc0\xc0' > functions/hid.1/report_desc
+-
+-# Create configuration
+-mkdir configs/c.1
+-mkdir configs/c.1/strings/0x409
+-
+-echo 0x80 > configs/c.1/bmAttributes
+-echo 200 > configs/c.1/MaxPower
+-echo "" > configs/c.1/strings/0x409/configuration
+-
+-# Link HID functions to configuration
+-ln -s functions/hid.0 configs/c.1
+-ln -s functions/hid.1 configs/c.1
+-
+-# Enable gadget
+-dev_name="1e6a0000.usb-vhub"
+-i=0
+-num_ports=5
+-base_usb_dir="/sys/bus/platform/devices/${dev_name}/${dev_name}:p"
+-while [ $i -lt $num_ports ]; do
+- port=$(($i + 1))
+- i=$port
+- if [ ! -e "${base_usb_dir}${port}/gadget/suspended" ]; then
+- break
+- fi
+-done
+-echo "${dev_name}:p${port}" > UDC
++
++if [ ! -e "${hid_conf_directory}" ]; then
++ create_hid
++else
++ cd "${hid_conf_directory}"
++fi
++
++if [ "$1" = "connect" ]; then
++ connect_hid
++elif [ "$1" = "disconnect" ]; then
++ disconnect_hid
++else
++ echo "Invalid option: $1. Use 'connect' or 'disconnect'."
++fi
+
+ cd "${original_directory}"
+diff --git a/ikvm_input.cpp b/ikvm_input.cpp
+index df12f2715585..c4cce5088461 100644
+--- a/ikvm_input.cpp
++++ b/ikvm_input.cpp
+@@ -16,6 +16,8 @@
+
+ #include "scancodes.hpp"
+
++namespace fs = std::filesystem;
++
+ namespace ikvm
+ {
+
+@@ -27,6 +29,54 @@ Input::Input(const std::string& kbdPath, const std::string& ptrPath) :
+ 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);
++}
++
++Input::~Input()
++{
++ if (keyboardFd >= 0)
++ {
++ close(keyboardFd);
++ }
++
++ if (pointerFd >= 0)
++ {
++ close(pointerFd);
++ }
++
++ disconnect();
++ hidUdcStream.close();
++}
++
++void Input::connect()
++{
++ try
++ {
++ for (const auto& port : fs::directory_iterator(usbVirtualHubPath))
++ {
++ if (fs::is_directory(port) && !fs::is_symlink(port) &&
++ !fs::exists(port.path() / "gadget/suspended"))
++ {
++ const std::string portId = port.path().filename();
++ hidUdcStream << portId << std::endl;
++ break;
++ }
++ }
++ }
++ catch (fs::filesystem_error& e)
++ {
++ log<level::ERR>("Failed to search USB virtual hub port",
++ entry("ERROR=%s", e.what()));
++ return;
++ }
++ catch (std::ofstream::failure& e)
++ {
++ log<level::ERR>("Failed to connect HID gadget",
++ entry("ERROR=%s", e.what()));
++ return;
++ }
++
+ if (!keyboardPath.empty())
+ {
+ keyboardFd = open(keyboardPath.c_str(), O_RDWR | O_CLOEXEC);
+@@ -56,16 +106,28 @@ Input::Input(const std::string& kbdPath, const std::string& ptrPath) :
+ }
+ }
+
+-Input::~Input()
++void Input::disconnect()
+ {
+ if (keyboardFd >= 0)
+ {
+ close(keyboardFd);
++ keyboardFd = -1;
+ }
+
+ if (pointerFd >= 0)
+ {
+ close(pointerFd);
++ pointerFd = -1;
++ }
++
++ try
++ {
++ hidUdcStream << "" << std::endl;
++ }
++ catch (std::ofstream::failure& e)
++ {
++ log<level::ERR>("Failed to disconnect HID gadget",
++ entry("ERROR=%s", e.what()));
+ }
+ }
+
+diff --git a/ikvm_input.hpp b/ikvm_input.hpp
+index 2adc7c106755..aae7cefbef6e 100644
+--- a/ikvm_input.hpp
++++ b/ikvm_input.hpp
+@@ -2,6 +2,8 @@
+
+ #include <rfb/rfb.h>
+
++#include <filesystem>
++#include <fstream>
+ #include <map>
+ #include <string>
+
+@@ -29,6 +31,10 @@ class Input
+ Input(Input&&) = default;
+ Input& operator=(Input&&) = default;
+
++ /* @brief Connects HID gadget to host */
++ void connect();
++ /* @brief Disconnects HID gadget from host */
++ void disconnect();
+ /*
+ * @brief RFB client key event handler
+ *
+@@ -72,6 +78,12 @@ class Input
+ 0x04, // left alt
+ 0x40 // right alt
+ };
++ /* @brief Path to the HID gadget UDC */
++ static constexpr const char* hidUdcPath =
++ "/sys/kernel/config/usb_gadget/obmc_hid/UDC";
++ /* @brief Path to the USB virtual hub */
++ static constexpr const char* usbVirtualHubPath =
++ "/sys/bus/platform/devices/1e6a0000.usb-vhub";
+ /*
+ * @brief Translates a RFB-specific key code to HID modifier bit
+ *
+@@ -109,6 +121,8 @@ class Input
+ * of which keys are down
+ */
+ std::map<int, int> keysDown;
++ /* @brief Handle of the HID gadget UDC */
++ std::ofstream hidUdcStream;
+ };
+
+ } // namespace ikvm
+diff --git a/ikvm_server.cpp b/ikvm_server.cpp
+index ebeaef049d04..1c2e981b7a72 100644
+--- a/ikvm_server.cpp
++++ b/ikvm_server.cpp
+@@ -178,6 +178,7 @@ void Server::clientGone(rfbClientPtr cl)
+
+ if (server->numClients-- == 1)
+ {
++ server->input.disconnect();
+ rfbMarkRectAsModified(server->server, 0, 0, server->video.getWidth(),
+ server->video.getHeight());
+ }
+@@ -193,6 +194,7 @@ enum rfbNewClientAction Server::newClient(rfbClientPtr cl)
+ cl->clientFramebufferUpdateRequestHook = clientFramebufferUpdateRequest;
+ if (!server->numClients++)
+ {
++ server->input.connect();
+ server->pendingResize = false;
+ server->frameCounter = 0;
+ }
+diff --git a/start-ipkvm.service b/start-ipkvm.service
+index 5f945b329a26..60234b231da3 100644
+--- a/start-ipkvm.service
++++ b/start-ipkvm.service
+@@ -4,7 +4,7 @@ ConditionPathIsMountPoint=/sys/kernel/config
+
+ [Service]
+ Restart=always
+-ExecStartPre=/usr/bin/create_usbhid.sh
++ExecStartPre=/usr/bin/create_usbhid.sh disconnect
+ ExecStart=/usr/bin/obmc-ikvm -v /dev/video0 -k /dev/hidg0 -p /dev/hidg1
+
+ [Install]
+--
+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 8de421d18..baa93bc04 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
@@ -5,4 +5,5 @@ SRCREV = "861337e8ec92767c4c88237ec5db494a2a67fa8d"
SRC_URI += " \
file://0003-Fix-keyboard-and-mouse-input-events-dropping-issue.patch \
+ file://0004-Connect-HID-gadget-device-dynamically.patch \
"
diff --git a/meta-openbmc-mods/meta-common/recipes-intel/host-misc-comm-manager/host-misc-comm-manager_git.bb b/meta-openbmc-mods/meta-common/recipes-intel/host-misc-comm-manager/host-misc-comm-manager_git.bb
index 0a07f5ab0..1a55391f9 100644
--- a/meta-openbmc-mods/meta-common/recipes-intel/host-misc-comm-manager/host-misc-comm-manager_git.bb
+++ b/meta-openbmc-mods/meta-common/recipes-intel/host-misc-comm-manager/host-misc-comm-manager_git.bb
@@ -11,7 +11,7 @@ LIC_FILES_CHKSUM = "file://LICENSE;md5=e3fc50a88d0a364313df4b21ef20c29e"
SRC_URI = "git://github.com/Intel-BMC/host-misc-comm-manager.git;protocol=ssh"
-SRCREV = "7e14ddf805cda0cdf3db564081144d9532e555cd"
+SRCREV = "17481c639999cda1bfc999fe1703290425c7ce45"
inherit cmake systemd
SYSTEMD_SERVICE_${PN} = "xyz.openbmc_project.Host.Misc.Manager.service"
diff --git a/meta-openbmc-mods/meta-common/recipes-intel/hsbp/hsbp-manager_git.bb b/meta-openbmc-mods/meta-common/recipes-intel/hsbp/hsbp-manager_git.bb
index 3a25900d5..b161868f2 100644
--- a/meta-openbmc-mods/meta-common/recipes-intel/hsbp/hsbp-manager_git.bb
+++ b/meta-openbmc-mods/meta-common/recipes-intel/hsbp/hsbp-manager_git.bb
@@ -2,7 +2,7 @@ SUMMARY = "HSBP Manager"
DESCRIPTION = "HSBP Manager monitors HSBPs through SMBUS"
SRC_URI = "git://github.com/openbmc/s2600wf-misc.git"
-SRCREV = "7045b4b283cf1405e832641fb79fcfb2b07c1acb"
+SRCREV = "c66735b6e99f69a00c2b5a0b286eb1c37251ccca"
PV = "0.1+git${SRCPV}"
LICENSE = "Apache-2.0"
diff --git a/meta-openbmc-mods/meta-common/recipes-intel/intel-pfr/files/pfr_image.py b/meta-openbmc-mods/meta-common/recipes-intel/intel-pfr/files/pfr_image.py
index b69639f32..c077e5318 100755
--- a/meta-openbmc-mods/meta-common/recipes-intel/intel-pfr/files/pfr_image.py
+++ b/meta-openbmc-mods/meta-common/recipes-intel/intel-pfr/files/pfr_image.py
@@ -14,7 +14,7 @@
# TODO: figure out if active and recovery actually have different sigs
# TODO: build hashmap from payload manifest
# TODO: figure out exact struct layout for PFR metadata
-import os, hashlib, struct, json, sys, subprocess, mmap, io, array, binascii, copy, shutil, re
+import os, hashlib, struct, json, sys, subprocess, mmap, io, array, binascii, copy, shutil, re, getopt
from array import array
from binascii import unhexlify
from hashlib import sha1, sha256, sha384, sha512
@@ -84,7 +84,7 @@ class pfm_i2c(object):
class pfr_bmc_image(object):
# json_file, firmware_file
- def __init__(self, manifest, firmware_file, build_ver, build_num, build_hash, sha):
+ def __init__(self, manifest, firmware_file, build_ver, build_num, build_hash, sha, output_filename):
self.manifest = load_manifest(manifest)
self.firmware_file = firmware_file
@@ -98,7 +98,7 @@ class pfr_bmc_image(object):
if self.sha == "1":
self.pfm_spi_size_hash = 32
self.sha_version = 0x1
- self.pfr_rom_file = 'image-mtd-pfr'
+ self.pfr_rom_file = output_filename
open(self.pfr_rom_file, 'a').close()
self.page_size = PAGE_SIZE
@@ -366,20 +366,59 @@ class pfr_bmc_image(object):
# write the padding bytes at the end
f.write(b'\xff' * padding_bytes)
+def usage(prog):
+ sys.stderr.write(prog +
+ " -m manifest -i rom-image -n build_version -b build_number -h build_hash -s sha -o output_file_name\n")
+
def main():
- if len(sys.argv) != 7: #< pfr_image.py manifest.json> <update.bin> <build_version> <build_number> <build_hash> <sha>
- print('usage: {} <manifest.json> <firmware.bin> <build_version> <build_number> <build_hash> <sha>'.format(sys.argv[0]))
- return
+ try:
+ opts, args = getopt.getopt(sys.argv[1:], "m:i:n:b:h:s:o:",
+ ["manifest=", "image=", "build_version=","build_number=","build_hash=","sha=", "output_file_name="])
+ except getopt.GetoptError as err:
+ sys.stderr.write(str(err) + "\n")
+ sys.exit(2)
+ json_file = None
+ firmware_file = None
+ build_ver = None
+ build_num = None
+ build_hash = None
+ sha = None
+ output_filename = None
+
+ for o, a in opts:
+ if o in ("-m", "--manifest"):
+ json_file = a
+ elif o in ("-i", "--image"):
+ firmware_file = a
+ elif o in ("-n", "--build_version"):
+ build_ver = a
+ elif o in ("-b", "--build_number"):
+ build_num = a
+ elif o in ("-h", "--build_hash"):
+ build_hash = a
+ elif o in ("-s", "--sha"):
+ sha = a
+ elif o in ("-o", "--output_file_name"):
+ output_filename = a
+ else:
+ usage(sys.argv[0])
+ assert False, "unhandled argument: " + o
+
+ if json_file is None or firmware_file is None or build_ver is None or build_num is None or build_hash is None or sha is None or output_filename is None:
+ usage(sys.argv[0])
+ sys.exit(-1)
+
+ print("manifest: %s" % json_file)
+ print("image: %s" % firmware_file)
+ print("build_ver: %s" % build_ver)
+ print("build_number: %s" % build_num)
+ print("build_hash: %s" % build_hash)
+ print("Sha: %s" % sha)
+ print("output_filename: %s" % output_filename)
- json_file = sys.argv[1]
- firmware_file = sys.argv[2]
- build_ver = sys.argv[3]
- build_num = sys.argv[4]
- build_hash = sys.argv[5]
- sha = sys.argv[6]
# function to generate BMC PFM, PBC header and BMC compressed image
- pfr_bmc_image(json_file, firmware_file, build_ver, build_num, build_hash, sha)
+ pfr_bmc_image(json_file, firmware_file, build_ver, build_num, build_hash, sha ,output_filename)
if __name__ == '__main__':
main()
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 e91a996b5..c6dd34bb1 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,3 +1,5 @@
# Enable downstream autobump
SRC_URI = "git://github.com/openbmc/pfr-manager"
-SRCREV = "deab6540336c8f37f076d709d77dd41456ab1605"
+SRCREV = "53b8700fd18873cffe7ee70b2306e7c66b2f7037"
+DEPENDS += " libgpiod \
+ "
diff --git a/meta-openbmc-mods/meta-common/recipes-intel/smbios/smbios-mdrv2.bb b/meta-openbmc-mods/meta-common/recipes-intel/smbios/smbios-mdrv2.bb
index 46f14d3ed..631a70cef 100644
--- a/meta-openbmc-mods/meta-common/recipes-intel/smbios/smbios-mdrv2.bb
+++ b/meta-openbmc-mods/meta-common/recipes-intel/smbios/smbios-mdrv2.bb
@@ -2,7 +2,7 @@ SUMMARY = "SMBIOS MDR version 2 service for Intel based platform"
DESCRIPTION = "SMBIOS MDR version 2 service for Intel based platfrom"
SRC_URI = "git://github.com/Intel-BMC/mdrv2.git;protocol=ssh"
-SRCREV = "5ae0c19064f010c9981cc90f4ddb2031887de4dc"
+SRCREV = "095102dfb5e2374834e33d1ec1a5e61388208a9e"
S = "${WORKDIR}/git"
@@ -15,6 +15,7 @@ inherit cmake pkgconfig
inherit obmc-phosphor-systemd
SYSTEMD_SERVICE_${PN} += "smbios-mdrv2.service"
+SYSTEMD_SERVICE_${PN} += "xyz.openbmc_project.cpuinfo.service"
DEPENDS += " \
autoconf-archive-native \
@@ -25,7 +26,8 @@ DEPENDS += " \
phosphor-dbus-interfaces \
phosphor-dbus-interfaces-native \
phosphor-logging \
+ libpeci \
+ i2c-tools \
"
-
PACKAGECONFIG ??= "${@bb.utils.filter('DISTRO_FEATURES', 'smbios-no-dimm', d)}"
PACKAGECONFIG[smbios-no-dimm] = "-DDIMM_DBUS=OFF, -DDIMM_DBUS=ON"
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0001-arm-dts-intel-s2600wf-dts-fixups.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0001-arm-dts-intel-s2600wf-dts-fixups.patch
new file mode 100644
index 000000000..d88fc2383
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0001-arm-dts-intel-s2600wf-dts-fixups.patch
@@ -0,0 +1,477 @@
+From 92c28f515166e4478dd447eb1d33409d14aed954 Mon Sep 17 00:00:00 2001
+From: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+Date: Tue, 7 Jul 2020 22:27:10 -0700
+Subject: [PATCH] arm: dts: intel s2600wf dts fixups
+
+Add fixups for Intel S2600WF dts.
+
+Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+---
+ .../arm/boot/dts/aspeed-bmc-intel-s2600wf.dts | 362 +++++++++++++++++-
+ 1 file changed, 343 insertions(+), 19 deletions(-)
+
+diff --git a/arch/arm/boot/dts/aspeed-bmc-intel-s2600wf.dts b/arch/arm/boot/dts/aspeed-bmc-intel-s2600wf.dts
+index 1deb30ec912c..daa85e947d48 100644
+--- a/arch/arm/boot/dts/aspeed-bmc-intel-s2600wf.dts
++++ b/arch/arm/boot/dts/aspeed-bmc-intel-s2600wf.dts
+@@ -3,14 +3,20 @@
+ /dts-v1/;
+
+ #include "aspeed-g5.dtsi"
++#include <dt-bindings/gpio/aspeed-gpio.h>
++#include <dt-bindings/i2c/i2c.h>
+
+ / {
+- model = "S2600WF BMC";
++ model = "Intel S2600WF BMC";
+ compatible = "intel,s2600wf-bmc", "aspeed,ast2500";
+
++ aliases {
++ serial4 = &uart5;
++ };
++
+ chosen {
+ stdout-path = &uart5;
+- bootargs = "earlyprintk";
++ bootargs = "console=ttyS4,115200 earlyprintk";
+ };
+
+ memory@80000000 {
+@@ -26,6 +32,32 @@
+ no-map;
+ reg = <0x7f000000 0x01000000>;
+ };
++
++ gfx_memory: framebuffer {
++ size = <0x01000000>;
++ alignment = <0x01000000>;
++ compatible = "shared-dma-pool";
++ reusable;
++ };
++
++ video_engine_memory: jpegbuffer {
++ size = <0x02000000>; /* 32M */
++ alignment = <0x01000000>;
++ compatible = "shared-dma-pool";
++ reusable;
++ };
++
++ ramoops@9eff0000{
++ compatible = "ramoops";
++ reg = <0x9eff0000 0x10000>;
++ record-size = <0x2000>;
++ console-size = <0x2000>;
++ };
++ };
++
++ vga-shared-memory {
++ compatible = "aspeed,ast2500-vga-sharedmem";
++ reg = <0x9ff00000 0x100000>;
+ };
+
+ iio-hwmon {
+@@ -36,6 +68,29 @@
+ <&adc 12>, <&adc 13>, <&adc 14>, <&adc 15>;
+ };
+
++ leds {
++ compatible = "gpio-leds";
++
++ identify {
++ default-state = "on";
++ gpios = <&gpio ASPEED_GPIO(S, 6) GPIO_ACTIVE_LOW>;
++ };
++
++ status_amber {
++ default-state = "off";
++ gpios = <&gpio ASPEED_GPIO(S, 5) GPIO_ACTIVE_LOW>;
++ };
++
++ status_green {
++ default-state = "keep";
++ gpios = <&gpio ASPEED_GPIO(S, 4) GPIO_ACTIVE_LOW>;
++ };
++ };
++
++ beeper {
++ compatible = "pwm-beeper";
++ pwms = <&timer 5 1000000 0>;
++ };
+ };
+
+ &fmc {
+@@ -44,35 +99,204 @@
+ status = "okay";
+ m25p,fast-read;
+ label = "bmc";
+-#include "openbmc-flash-layout.dtsi"
++#include "openbmc-flash-layout-intel-64MB.dtsi"
+ };
+ };
+
+-&spi1 {
++&espi {
+ status = "okay";
+- pinctrl-names = "default";
+- pinctrl-0 = <&pinctrl_spi1_default>;
++};
+
+- flash@0 {
+- status = "okay";
+- m25p,fast-read;
+- label = "pnor";
++&jtag {
++ status = "okay";
++};
++
++&peci0 {
++ status = "okay";
++ gpios = <&gpio ASPEED_GPIO(F, 6) 0>;
++};
++
++&syscon {
++ uart-clock-high-speed;
++ status = "okay";
++
++ misc_control {
++ compatible = "aspeed,bmc-misc";
++ uart_port_debug {
++ offset = <0x2c>;
++ bit-mask = <0x1>;
++ bit-shift = <10>;
++ read-only;
++ };
++ p2a-bridge {
++ offset = <0x180>;
++ bit-mask = <0x1>;
++ bit-shift = <1>;
++ read-only;
++ };
++ boot-2nd-flash {
++ offset = <0x70>;
++ bit-mask = <0x1>;
++ bit-shift = <17>;
++ read-only;
++ };
++ chip_id {
++ offset = <0x150>;
++ bit-mask = <0x0fffffff 0xffffffff>;
++ bit-shift = <0>;
++ read-only;
++ reg-width = <64>;
++ hash-data = "d44f9b804976fa23c2e25d62f16154d26520a7e24c5555095fd1b55c027804f1570dcd16189739c640cd7d9a6ce14944a2c4eaf1dc429eed6940e8a83498a474";
++ };
+ };
+ };
+
+-&uart5 {
++&adc {
+ status = "okay";
+ };
+
+-&mac0 {
++&gpio {
++ status = "okay";
++ /* Enable GPIOE0 and GPIOE2 pass-through by default */
++ pinctrl-names = "pass-through";
++ pinctrl-0 = <&pinctrl_gpie0_default
++ &pinctrl_gpie2_default>;
++ gpio-line-names =
++ /*A0-A7*/ "","","","","","","","",
++ /*B0-B7*/ "","","","","","","","",
++ /*C0-C7*/ "","","","","","","","",
++ /*D0-D7*/ "","","","","","","","",
++ /*E0-E7*/ "RESET_BUTTON","RESET_OUT","POWER_BUTTON","POWER_OUT","","","","",
++ /*F0-F7*/ "NMI_OUT","","","","CPU_ERR0","CPU_ERR1","","",
++ /*G0-G7*/ "CPU_ERR2","CPU_CATERR","PCH_BMC_THERMTRIP","LCP_ENTER_BUTTON","LCP_LEFT_BUTTON","FM_BMC_BOARD_SKU_ID5_N","","",
++ /*H0-H7*/ "","","","FM_NODE_ID_1","FM_NODE_ID_2","FM_NODE_ID_3","FM_NODE_ID_4","FM_240VA_STATUS",
++ /*I0-I7*/ "FM_SYS_FAN0_PRSNT_D_N","FM_SYS_FAN1_PRSNT_D_N","FM_SYS_FAN2_PRSNT_D_N","FM_SYS_FAN3_PRSNT_D_N","FM_SYS_FAN4_PRSNT_D_N","FM_SYS_FAN5_PRSNT_D_N","","",
++ /*J0-J7*/ "","","","","","","","",
++ /*K0-K7*/ "","","","","","","","",
++ /*L0-L7*/ "","","","","","","","",
++ /*M0-M7*/ "","","","","","","","",
++ /*N0-N7*/ "","","","","","","","",
++ /*O0-O7*/ "","","","","","","","",
++ /*P0-P7*/ "","","","","","","","",
++ /*Q0-Q7*/ "","","","","","","","PWR_DEBUG_N",
++ /*R0-R7*/ "","XDP_PRST_N","","","","","","CHASSIS_INTRUSION",
++ /*S0-S7*/ "REMOTE_DEBUG_ENABLE","SYSPWROK","RSMRST_N","","","","","",
++ /*T0-T7*/ "","","","","","","","",
++ /*U0-U7*/ "","","","","","","","",
++ /*V0-V7*/ "","","","","","","","",
++ /*W0-W7*/ "","","","","","","","",
++ /*X0-X7*/ "","","","","","","","",
++ /*Y0-Y7*/ "SIO_S3","SIO_S5","","SIO_ONCONTROL","","","","",
++ /*Z0-Z7*/ "","SIO_POWER_GOOD","","","","","","",
++ /*AA0-AA7*/ "P3VBAT_BRIDGE_EN","","","","PREQ_N","TCK_MUX_SEL","SMI","POST_COMPLETE",
++ /*AB0-AB7*/ "","NMI_BUTTON","ID_BUTTON","PS_PWROK","","","","",
++ /*AC0-AC7*/ "","","","","","","","";
++};
++
++&sgpio {
+ status = "okay";
++ gpio-line-names =
++ /* SGPIO output lines */
++ /*OA0-OA7*/ "","","","","","","","",
++ /*OB0-OB7*/ "LED_CPU1_CH1_DIMM1_FAULT","LED_CPU1_CH1_DIMM2_FAULT","LED_CPU1_CH2_DIMM1_FAULT","LED_CPU1_CH2_DIMM2_FAULT","LED_CPU1_CH3_DIMM1_FAULT","LED_CPU1_CH3_DIMM2_FAULT","LED_CPU1_CH4_DIMM1_FAULT","LED_CPU1_CH4_DIMM2_FAULT",
++ /*OC0-OC7*/ "LED_CPU1_CH5_DIMM1_FAULT","LED_CPU1_CH5_DIMM2_FAULT","LED_CPU1_CH6_DIMM1_FAULT","LED_CPU1_CH6_DIMM2_FAULT","LED_FAN1_FAULT","LED_FAN2_FAULT","LED_FAN3_FAULT","LED_FAN4_FAULT",
++ /*OD0-OD7*/ "LED_FAN5_FAULT","LED_FAN6_FAULT","LED_FAN7_FAULT","LED_FAN8_FAULT","LED_CPU2_CH1_DIMM1_FAULT","LED_CPU1_CH1_DIMM2_FAULT","LED_CPU2_CH2_DIMM1_FAULT","LED_CPU2_CH2_DIMM2_FAULT",
++ /*OE0-OE7*/ "LED_CPU2_CH3_DIMM1_FAULT","LED_CPU2_CH3_DIMM2_FAULT","LED_CPU2_CH4_DIMM1_FAULT","LED_CPU2_CH4_DIMM2_FAULT","LED_CPU2_CH5_DIMM1_FAULT","LED_CPU2_CH5_DIMM2_FAULT","LED_CPU2_CH6_DIMM1_FAULT","LED_CPU2_CH6_DIMM2_FAULT",
++ /*OF0-OF7*/ "LED_CPU3_CH1_DIMM1_FAULT","LED_CPU3_CH1_DIMM2_FAULT","LED_CPU3_CH2_DIMM1_FAULT","LED_CPU3_CH2_DIMM2_FAULT","LED_CPU3_CH3_DIMM1_FAULT","LED_CPU3_CH3_DIMM2_FAULT","LED_CPU3_CH4_DIMM1_FAULT","LED_CPU3_CH4_DIMM2_FAULT",
++ /*OG0-OG7*/ "LED_CPU3_CH5_DIMM1_FAULT","LED_CPU3_CH5_DIMM2_FAULT","LED_CPU3_CH6_DIMM1_FAULT","LED_CPU3_CH6_DIMM2_FAULT","LED_CPU4_CH1_DIMM1_FAULT","LED_CPU4_CH1_DIMM2_FAULT","LED_CPU4_CH2_DIMM1_FAULT","LED_CPU4_CH2_DIMM2_FAULT",
++ /*OH0-OH7*/ "LED_CPU4_CH3_DIMM1_FAULT","LED_CPU4_CH3_DIMM2_FAULT","LED_CPU4_CH4_DIMM1_FAULT","LED_CPU4_CH4_DIMM2_FAULT","LED_CPU4_CH5_DIMM1_FAULT","LED_CPU4_CH5_DIMM2_FAULT","LED_CPU4_CH6_DIMM1_FAULT","LED_CPU4_CH6_DIMM2_FAULT",
++ /*OI0-OI7*/ "","","","","","","","",
++ /*OJ0-OJ7*/ "","","","","","","","",
++ /*DUMMY*/ "","","","","","","","",
++ /*DUMMY*/ "","","","","","","","",
+
++ /* SGPIO input lines */
++ /*IA0-IA7*/ "CPU1_PRESENCE","CPU1_THERMTRIP","CPU1_VRHOT","CPU1_FIVR_FAULT","CPU1_MEM_ABCD_VRHOT","CPU1_MEM_EFGH_VRHOT","","",
++ /*IB0-IB7*/ "CPU1_MISMATCH","CPU1_MEM_THERM_EVENT","CPU2_PRESENCE","CPU2_THERMTRIP","CPU2_VRHOT","CPU2_FIVR_FAULT","CPU2_MEM_ABCD_VRHOT","CPU2_MEM_EFGH_VRHOT",
++ /*IC0-IC7*/ "","","CPU2_MISMATCH","CPU2_MEM_THERM_EVENT","","","","",
++ /*ID0-ID7*/ "","","","","","","","",
++ /*IE0-IE7*/ "","","","","","","","",
++ /*IF0-IF7*/ "SGPIO_PLD_MINOR_REV_BIT0","SGPIO_PLD_MINOR_REV_BIT1","SGPIO_PLD_MINOR_REV_BIT2","SGPIO_PLD_MINOR_REV_BIT3","SGPIO_PLD_MAJOR_REV_BIT0","SGPIO_PLD_MAJOR_REV_BIT1","SGPIO_PLD_MAJOR_REV_BIT2","SGPIO_PLD_MAJOR_REV_BIT3",
++ /*IG0-IG7*/ "MAIN_PLD_MINOR_REV_BIT0","MAIN_PLD_MINOR_REV_BIT1","MAIN_PLD_MINOR_REV_BIT2","MAIN_PLD_MINOR_REV_BIT3","MAIN_PLD_MAJOR_REV_BIT0","MAIN_PLD_MAJOR_REV_BIT1","MAIN_PLD_MAJOR_REV_BIT2","MAIN_PLD_MAJOR_REV_BIT3",
++ /*IH0-IH7*/ "","","","","","","","",
++ /*II0-II7*/ "","","","","","","","",
++ /*IJ0-IJ7*/ "","","","","","","","";
++};
++
++&kcs3 {
++ kcs_addr = <0xCA2>;
++ status = "okay";
++};
++
++&kcs4 {
++ kcs_addr = <0xCA4>;
++ status = "okay";
++};
++
++&sio_regs {
++ status = "okay";
++ sio_status {
++ offset = <0x8C>;
++ bit-mask = <0x1F>;
++ bit-shift = <4>;
++ };
++};
++
++&lpc_sio {
++ status = "okay";
++};
++
++&lpc_snoop {
++ snoop-ports = <0x80>;
++ status = "okay";
++};
++
++&mbox {
++ status = "okay";
++};
++
++&uart_routing {
++ status = "okay";
++};
++
++&uart1 {
++ status = "okay";
+ pinctrl-names = "default";
+- pinctrl-0 = <&pinctrl_rmii1_default>;
+- clocks = <&syscon ASPEED_CLK_GATE_MAC1CLK>,
+- <&syscon ASPEED_CLK_MAC1RCLK>;
+- clock-names = "MACCLK", "RCLK";
+- use-ncsi;
++ pinctrl-0 = <&pinctrl_txd1_default
++ &pinctrl_rxd1_default
++ &pinctrl_nrts1_default
++ &pinctrl_ndtr1_default
++ &pinctrl_ndsr1_default
++ &pinctrl_ncts1_default
++ &pinctrl_ndcd1_default
++ &pinctrl_nri1_default>;
++};
++
++&uart2 {
++ status = "okay";
++ pinctrl-names = "default";
++ pinctrl-0 = <&pinctrl_txd2_default
++ &pinctrl_rxd2_default
++ &pinctrl_nrts2_default
++ &pinctrl_ndtr2_default
++ &pinctrl_ndsr2_default
++ &pinctrl_ncts2_default
++ &pinctrl_ndcd2_default
++ &pinctrl_nri2_default>;
++};
++
++&uart3 {
++ status = "okay";
++};
++
++&uart4 {
++ status = "okay";
++ pinctrl-names = "default";
++ pinctrl-0 = <>;
++};
++
++&uart5 {
++ status = "okay";
+ };
+
+ &mac1 {
+@@ -82,44 +306,87 @@
+ pinctrl-0 = <&pinctrl_rgmii2_default &pinctrl_mdio2_default>;
+ };
+
++&mac0 {
++ status = "okay";
++ use-ncsi;
++
++ pinctrl-names = "default";
++ pinctrl-0 = <&pinctrl_rmii1_default>;
++};
++
++&i2c0 {
++ multi-master;
++ general-call;
++ aspeed,dma-buf-size = <4095>;
++ aspeed,hw-timeout-ms = <300>;
++ status = "okay";
++};
++
+ &i2c1 {
++ multi-master;
++ aspeed,dma-buf-size = <4095>;
++ aspeed,hw-timeout-ms = <300>;
+ status = "okay";
+ };
+
+ &i2c2 {
++ multi-master;
++ aspeed,dma-buf-size = <4095>;
++ aspeed,hw-timeout-ms = <300>;
+ status = "okay";
+ };
+
+ &i2c3 {
++ multi-master;
++ aspeed,dma-buf-size = <4095>;
++ aspeed,hw-timeout-ms = <300>;
+ status = "okay";
+ };
+
+ &i2c4 {
++ multi-master;
++ aspeed,dma-buf-size = <4095>;
++ aspeed,hw-timeout-ms = <300>;
+ status = "okay";
+ };
+
+ &i2c5 {
++ bus-frequency = <1000000>;
++ multi-master;
++ aspeed,dma-buf-size = <4095>;
++ aspeed,hw-timeout-ms = <300>;
+ status = "okay";
+ };
+
+ &i2c6 {
++ multi-master;
++ aspeed,dma-buf-size = <4095>;
++ aspeed,hw-timeout-ms = <300>;
+ status = "okay";
+ };
+
+ &i2c7 {
++ multi-master;
++ #retries = <3>;
++ aspeed,dma-buf-size = <4095>;
++ aspeed,hw-timeout-ms = <300>;
+ status = "okay";
+ };
+
+ &i2c13 {
++ multi-master;
++ aspeed,dma-buf-size = <4095>;
++ aspeed,hw-timeout-ms = <300>;
+ status = "okay";
+ };
+
+ &gfx {
+ status = "okay";
++ memory-region = <&gfx_memory>;
+ };
+
+-&pinctrl {
+- aspeed,external-nodes = <&gfx &lhc>;
++&vuart {
++ status = "okay";
+ };
+
+ &pwm_tacho {
+@@ -129,4 +396,61 @@
+ &pinctrl_pwm2_default &pinctrl_pwm3_default
+ &pinctrl_pwm4_default &pinctrl_pwm5_default
+ &pinctrl_pwm6_default &pinctrl_pwm7_default>;
++
++ fan@0 {
++ reg = <0x00>;
++ aspeed,fan-tach-ch = /bits/ 8 <0x00 0x01>;
++ };
++ fan@1 {
++ reg = <0x01>;
++ aspeed,fan-tach-ch = /bits/ 8 <0x02 0x03>;
++ };
++ fan@2 {
++ reg = <0x02>;
++ aspeed,fan-tach-ch = /bits/ 8 <0x04 0x05>;
++ };
++ fan@3 {
++ reg = <0x03>;
++ aspeed,fan-tach-ch = /bits/ 8 <0x06 0x07>;
++ };
++ fan@4 {
++ reg = <0x04>;
++ aspeed,fan-tach-ch = /bits/ 8 <0x08 0x09>;
++ };
++ fan@5 {
++ reg = <0x05>;
++ aspeed,fan-tach-ch = /bits/ 8 <0x0A 0x0B>;
++ };
++ fan@6 {
++ reg = <0x06>;
++ aspeed,fan-tach-ch = /bits/ 8 <0x0C 0x0D>;
++ };
++ fan@7 {
++ reg = <0x07>;
++ aspeed,fan-tach-ch = /bits/ 8 <0x0E 0x0F>;
++ };
++
++};
++
++&timer {
++/*
++ * Available settings:
++ * fttmr010,pwm-outputs = <5>, <6>, <7>, <8>;
++ * pinctrl-0 = <&pinctrl_timer5_default &pinctrl_timer6_default
++ * &pinctrl_timer7_default &pinctrl_timer8_default>;
++ */
++ fttmr010,pwm-outputs = <6>;
++ pinctrl-names = "default";
++ pinctrl-0 = <&pinctrl_timer6_default>;
++ #pwm-cells = <3>;
++ status = "okay";
++};
++
++&video {
++ status = "okay";
++ memory-region = <&video_engine_memory>;
++};
++
++&vhub {
++ status = "okay";
+ };
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0095-pwm-and-tach-driver-changes-for-ast2600.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0095-pwm-and-tach-driver-changes-for-ast2600.patch
index 2d624d10f..badda2d60 100644
--- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0095-pwm-and-tach-driver-changes-for-ast2600.patch
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0095-pwm-and-tach-driver-changes-for-ast2600.patch
@@ -21,7 +21,7 @@ index 1894f6ad5edb..9551a17e7f55 100644
#define PWM_RISING_RISING_BIT (0) //pwm rising point bit [7:0]
+#define PWM_PERIOD_MAX 255
-+#define PWM_FALLING_DEFAULT 150 /* 58% */
++#define PWM_FALLING_DEFAULT 255 /* 100% */
+
#define ASPEED_TACHO_CTRL 0x08 //TACH0 General Register
#define ASPEED_TACHO_CTRL_CH(x) ((x * 0x10) + 0x08)
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0116-watchdog-aspeed-fix-AST2600-support.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0116-watchdog-aspeed-fix-AST2600-support.patch
index 3f71219de..33e142c30 100644
--- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0116-watchdog-aspeed-fix-AST2600-support.patch
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0116-watchdog-aspeed-fix-AST2600-support.patch
@@ -1,31 +1,50 @@
-From f911c7c994bf57685254f3b92e03e999d9cf058a Mon Sep 17 00:00:00 2001
+From 02acccc7dd2ade8cf48aff2312ebb8752c8c98eb Mon Sep 17 00:00:00 2001
From: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
Date: Thu, 25 Jun 2020 23:56:15 -0700
Subject: [PATCH] watchdog: aspeed: fix AST2600 support
AST2600 provides different function of WDT0C[4] and it doesn't
-provides WDT10[1] so this commit fixes driver to make it don't
-use these register bits in case of AST2600.
+provides WDT10[1] so this commit fixes driver to make it available
+on AST2600.
Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
---
- drivers/watchdog/aspeed_wdt.c | 13 +++++++------
- 1 file changed, 7 insertions(+), 6 deletions(-)
+ drivers/watchdog/aspeed_wdt.c | 21 ++++++++++++---------
+ 1 file changed, 12 insertions(+), 9 deletions(-)
diff --git a/drivers/watchdog/aspeed_wdt.c b/drivers/watchdog/aspeed_wdt.c
-index 7e00960651fa..5a74b439e3b1 100644
+index 7e00960651fa..b0afeb939686 100644
--- a/drivers/watchdog/aspeed_wdt.c
+++ b/drivers/watchdog/aspeed_wdt.c
-@@ -279,6 +279,8 @@ static int aspeed_wdt_probe(struct platform_device *pdev)
+@@ -47,7 +47,8 @@ MODULE_DEVICE_TABLE(of, aspeed_wdt_of_table);
+ #define WDT_CTRL_RESET_MODE_SOC (0x00 << 5)
+ #define WDT_CTRL_RESET_MODE_FULL_CHIP (0x01 << 5)
+ #define WDT_CTRL_RESET_MODE_ARM_CPU (0x10 << 5)
+-#define WDT_CTRL_1MHZ_CLK BIT(4)
++#define WDT_CTRL_1MHZ_CLK BIT(4) /* ast2400/2500 */
++#define WDT_CTRL_WDT_RST_BY_SOC_RST BIT(4) /* ast2600 */
+ #define WDT_CTRL_WDT_EXT BIT(3)
+ #define WDT_CTRL_WDT_INTR BIT(2)
+ #define WDT_CTRL_RESET_SYSTEM BIT(1)
+@@ -277,12 +278,15 @@ static int aspeed_wdt_probe(struct platform_device *pdev)
+ * On clock rates:
+ * - ast2400 wdt can run at PCLK, or 1MHz
* - ast2500 only runs at 1MHz, hard coding bit 4 to 1
- * - ast2600 always runs at 1MHz
+- * - ast2600 always runs at 1MHz
++ * - ast2600 uses WDT0C[4] as 'Enable WDT to be reset by SOC reset'
*
-+ * Note: ast2600 uses WDT0C[4] as 'Enable WDT to be reset by SOC reset'
-+ *
* Set the ast2400 to run at 1MHz as it simplifies the driver.
*/
- if (of_device_is_compatible(np, "aspeed,ast2400-wdt"))
-@@ -367,13 +369,12 @@ static int aspeed_wdt_probe(struct platform_device *pdev)
+- if (of_device_is_compatible(np, "aspeed,ast2400-wdt"))
++ if (of_device_is_compatible(np, "aspeed,ast2400-wdt") ||
++ of_device_is_compatible(np, "aspeed,ast2500-wdt"))
+ wdt->ctrl = WDT_CTRL_1MHZ_CLK;
++ else if (of_device_is_compatible(np, "aspeed,ast2600-wdt"))
++ wdt->ctrl = WDT_CTRL_WDT_RST_BY_SOC_RST;
+
+ /*
+ * Control reset on a per-device basis to ensure the
+@@ -367,13 +371,12 @@ static int aspeed_wdt_probe(struct platform_device *pdev)
writel(duration - 1, wdt->base + WDT_RESET_WIDTH);
}
@@ -45,5 +64,5 @@ index 7e00960651fa..5a74b439e3b1 100644
dev_set_drvdata(dev, wdt);
--
-2.7.4
+2.17.1
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0118-Recalculate-AW-FCS-on-WrEndPointConfig-command.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0118-Recalculate-AW-FCS-on-WrEndPointConfig-command.patch
new file mode 100644
index 000000000..af173e71d
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0118-Recalculate-AW-FCS-on-WrEndPointConfig-command.patch
@@ -0,0 +1,34 @@
+From 2453c89ead650ab8e21f13c1b0a1b4054e0e7067 Mon Sep 17 00:00:00 2001
+From: "Jason M. Bills" <jason.m.bills@linux.intel.com>
+Date: Mon, 27 Jul 2020 11:27:47 -0700
+Subject: [PATCH] Recalculate AW FCS on WrEndPointConfig command
+
+The WrEndPointConfig command requires recalculating the AW FCS
+on retry, so set the has_aw_fcs parameter to true.
+
+Tested:
+Ran a WrEndPointConfig command with C-states enabled to confirm
+that it correctly retries the command:
+peci_cmds WrEndpointConfigPCILocal 0 13 12 0 0x2d4 0x601e0
+
+Signed-off-by: Jason M. Bills <jason.m.bills@linux.intel.com>
+---
+ drivers/peci/peci-core.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/peci/peci-core.c b/drivers/peci/peci-core.c
+index 426ee2be3271..ba561bf810f9 100644
+--- a/drivers/peci/peci-core.c
++++ b/drivers/peci/peci-core.c
+@@ -1059,7 +1059,7 @@ static int peci_cmd_wr_end_pt_cfg(struct peci_adapter *adapter, void *vmsg)
+ return -EINVAL;
+ }
+
+- ret = peci_xfer_with_retries(adapter, msg, false);
++ ret = peci_xfer_with_retries(adapter, msg, true);
+
+ out:
+ umsg->cc = msg->rx_buf[0];
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/intel.cfg b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/intel.cfg
index 5f453510a..077b83bac 100644
--- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/intel.cfg
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/intel.cfg
@@ -13,6 +13,7 @@ CONFIG_PECI_ASPEED=y
CONFIG_SENSORS_PECI_CPUTEMP=y
CONFIG_SENSORS_PECI_DIMMTEMP=y
CONFIG_SENSORS_PECI_CPUPOWER=y
+CONFIG_SENSORS_PECI_DIMMPOWER=y
CONFIG_CONFIGFS_FS=y
CONFIG_BLK_DEV_RAM_SIZE=49152
CONFIG_MAGIC_SYSRQ=y
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 b176446c3..8250ec919 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
@@ -8,6 +8,7 @@ do_compile_prepend(){
SRC_URI += " \
file://intel.cfg \
file://0001-arm-dts-add-DTS-for-Intel-ast2500-platforms.patch \
+ file://0001-arm-dts-intel-s2600wf-dts-fixups.patch \
file://0001-arm-dts-add-DTS-for-Intel-ast2600-platforms.patch \
file://0001-arm-dts-base-aspeed-g6-dtsi-fixups.patch \
file://0002-Enable-pass-through-on-GPIOE1-and-GPIOE3-free.patch \
@@ -84,6 +85,7 @@ SRC_URI += " \
file://0112-AST2600-enable-UART-routing.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 \
"
SRC_URI += "${@bb.utils.contains('IMAGE_FSTYPES', 'intel-pfr', 'file://0005-128MB-flashmap-for-PFR.patch', '', d)}"
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/configuration/entity-manager_%.bbappend b/meta-openbmc-mods/meta-common/recipes-phosphor/configuration/entity-manager_%.bbappend
index e76c23fa6..cf402206b 100644
--- a/meta-openbmc-mods/meta-common/recipes-phosphor/configuration/entity-manager_%.bbappend
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/configuration/entity-manager_%.bbappend
@@ -1,6 +1,6 @@
# this is here just to bump faster than upstream
SRC_URI = "git://github.com/openbmc/entity-manager.git"
-SRCREV = "ac09fe44dba113aacee1d2fd995e137c0d5ea18e"
+SRCREV = "e18edb5badc2e16181cfc464a6ccd0ef51dc4548"
FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0028-MCTP-Daemon-D-Bus-interface-definition.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0028-MCTP-Daemon-D-Bus-interface-definition.patch
index dc44d7a0d..e6afc0117 100644
--- a/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0028-MCTP-Daemon-D-Bus-interface-definition.patch
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0028-MCTP-Daemon-D-Bus-interface-definition.patch
@@ -1,4 +1,4 @@
-From 9bcc45f1a4d872e9968fdebf675c5fff6921c2f3 Mon Sep 17 00:00:00 2001
+From 65d1772312a76ebfdac6391bb97287c62f18c43f Mon Sep 17 00:00:00 2001
From: "Kowalski, Mariusz" <mariusz.kowalski@intel.com>
Date: Thu, 27 Feb 2020 15:48:56 +0100
Subject: [PATCH] MCTP Daemon D-Bus interface definition.
@@ -12,14 +12,14 @@ Signed-off-by: Mariusz Kowalski <mariusz.kowalski@intel.com>
Signed-off-by: Karol Wachowski <karol.wachowski@intel.com>
Change-Id: Ida66f8ffcf00003655edcb0fb0112202797b8e1a
---
- xyz/openbmc_project/MCTP/Base.interface.yaml | 231 ++++++++++++++++++
+ xyz/openbmc_project/MCTP/Base.interface.yaml | 227 ++++++++++++++++++
.../MCTP/Binding/PCIe.interface.yaml | 29 +++
.../MCTP/Binding/SMBus.interface.yaml | 17 ++
.../MCTP/BusOwner.interface.yaml | 17 ++
- .../MCTP/Endpoint.interface.yaml | 19 ++
- xyz/openbmc_project/MCTP/README.md | 38 +++
+ .../MCTP/Endpoint.interface.yaml | 13 +
+ xyz/openbmc_project/MCTP/README.md | 43 ++++
.../MCTP/SupportedMessageTypes.interface.yaml | 36 +++
- 7 files changed, 387 insertions(+)
+ 7 files changed, 382 insertions(+)
create mode 100644 xyz/openbmc_project/MCTP/Base.interface.yaml
create mode 100644 xyz/openbmc_project/MCTP/Binding/PCIe.interface.yaml
create mode 100644 xyz/openbmc_project/MCTP/Binding/SMBus.interface.yaml
@@ -30,10 +30,10 @@ Change-Id: Ida66f8ffcf00003655edcb0fb0112202797b8e1a
diff --git a/xyz/openbmc_project/MCTP/Base.interface.yaml b/xyz/openbmc_project/MCTP/Base.interface.yaml
new file mode 100644
-index 0000000..f27c1c7
+index 0000000..9438551
--- /dev/null
+++ b/xyz/openbmc_project/MCTP/Base.interface.yaml
-@@ -0,0 +1,231 @@
+@@ -0,0 +1,227 @@
+description: >
+ Mandatory interface for each instance of the MCTP Daemon to expose
+ the base MCTP daemon and medium type interfaces.
@@ -153,10 +153,6 @@ index 0000000..f27c1c7
+ type: boolean
+ description: Support for statically/dynamicly allocated IDs
+
-+ - name: Uuid
-+ type: array[byte]
-+ description: Guid - 16bytes
-+
+ - name: BindingMode
+ type: enum[self.BindingModeTypes]
+ description: Bus Owner / Endpoint / Bridge
@@ -348,20 +344,14 @@ index 0000000..d46298e
+ description: Indicates Eid pool is managed by self
diff --git a/xyz/openbmc_project/MCTP/Endpoint.interface.yaml b/xyz/openbmc_project/MCTP/Endpoint.interface.yaml
new file mode 100644
-index 0000000..b7f9a67
+index 0000000..e4ba4d0
--- /dev/null
+++ b/xyz/openbmc_project/MCTP/Endpoint.interface.yaml
-@@ -0,0 +1,19 @@
+@@ -0,0 +1,13 @@
+description:
+ Interface exposed by discovered MCTP endpoints.
+
+properties:
-+ - name: Uuid
-+ type: array[byte]
-+ description: >
-+ Universally unique identifier (UUID), also referred to as a globally
-+ unique ID (GUID), for the management controller or management device.
-+
+ - name: Mode
+ type: enum[xyz.openbmc_project.MCTP.Base.BindingModeTypes]
+ description: Endpoint / BusOwner / Bridge
@@ -373,10 +363,10 @@ index 0000000..b7f9a67
+ MCTP network within a platform.
diff --git a/xyz/openbmc_project/MCTP/README.md b/xyz/openbmc_project/MCTP/README.md
new file mode 100644
-index 0000000..3255ef2
+index 0000000..c819dbb
--- /dev/null
+++ b/xyz/openbmc_project/MCTP/README.md
-@@ -0,0 +1,38 @@
+@@ -0,0 +1,43 @@
+# MCTP Daemon
+
+## Overview
@@ -405,16 +395,21 @@ index 0000000..3255ef2
+4. Binding interface `xyz.openbmc_project.MCTP.Binding.PCIe` or
+`xyz.openbmc_project.MCTP.Binding.SMBus` as per the physical medium in which
+this MCTP Daemon is instantiated.
++5. Common UUID interface `xyz.openbmc_project.Common.UUID` which exposes UUID
++in RFC4122 format.
+
+#### Endpoint object
+Exposed under the path `/xyz/openbmc_project/mctp/device/<eid>` with the
+following interfaces.
+1. `xyz.openbmc_project.MCTP.SupportedMessageTypes` which exposes supported MCTP
+message types for the discovered MCTP Endpoint.
-+2. `xyz.openbmc_project.MCTP.Endpoint` which exposes properties like UUID and endpoint
-+mode (to identify Bus Owner or Bridge or Endpoint) for the discovered MCTP Endpoint.
++2. `xyz.openbmc_project.MCTP.Endpoint` which exposes properties like Network ID
++and endpoint mode (to identify Bus Owner or Bridge or Endpoint) for the discovered
++MCTP Endpoint.
+3. `xyz.openbmc_project.MCTP.Bridge` available only for discovered MCTP Bridges to
+expose properties like EID pool. (TBD)
++4. Common UUID interface `xyz.openbmc_project.Common.UUID` which exposes UUID
++in RFC4122 format.
diff --git a/xyz/openbmc_project/MCTP/SupportedMessageTypes.interface.yaml b/xyz/openbmc_project/MCTP/SupportedMessageTypes.interface.yaml
new file mode 100644
index 0000000..fa447ee
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/fans/phosphor-pid-control_%.bbappend b/meta-openbmc-mods/meta-common/recipes-phosphor/fans/phosphor-pid-control_%.bbappend
index 5efc383f0..2e4e23d40 100644
--- a/meta-openbmc-mods/meta-common/recipes-phosphor/fans/phosphor-pid-control_%.bbappend
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/fans/phosphor-pid-control_%.bbappend
@@ -5,6 +5,6 @@ SYSTEMD_SERVICE_${PN} = "phosphor-pid-control.service"
EXTRA_OECONF = "--enable-configure-dbus=yes"
SRC_URI = "git://github.com/openbmc/phosphor-pid-control.git"
-SRCREV = "4b36f265a10048127d93e4b70916c181827c9af2"
+SRCREV = "6fc301fbc3775730a0e69f215110ec93bd9026f3"
FILES_${PN} = "${bindir}/swampd ${bindir}/setsensor"
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0013-remove-image-file-on-pre-script-failures.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0013-remove-image-file-on-pre-script-failures.patch
new file mode 100644
index 000000000..d5d0f513e
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0013-remove-image-file-on-pre-script-failures.patch
@@ -0,0 +1,40 @@
+From ae3a9616b44677f20b4ca534c3f55ccb478fdf55 Mon Sep 17 00:00:00 2001
+From: Vernon Mauery <vernon.mauery@intel.com>
+Date: Thu, 16 Jul 2020 14:16:28 -0700
+Subject: [PATCH] remove image file on pre-script failures
+
+Multiple back-to-back updates of bad images will cause the software
+manager to leave junk images hanging around. This is part of a fix that
+will remove them if the software manager never gets around to launching
+the fwupd.sh script. The other part is that the fwupd.sh script must
+always delete the image file on exit, success or failure.
+
+Tested: posted a garbage file, saw that it was deleted even though
+ fwupd.sh was never invoked.
+
+Change-Id: I6b049916a3edcb48f9d4ebe0d4715b94214b4feb
+Signed-off-by: Vernon Mauery <vernon.mauery@intel.com>
+---
+ watch.cpp | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+diff --git a/watch.cpp b/watch.cpp
+index ccdf594..c738945 100644
+--- a/watch.cpp
++++ b/watch.cpp
+@@ -106,6 +106,15 @@ int Watch::callback(sd_event_source* /* s */, int fd, uint32_t revents,
+ {
+ log<level::ERR>("Error processing image",
+ entry("IMAGE=%s", tarballPath.c_str()));
++ std::error_code ec{};
++ fs::remove_all(tarballPath, ec);
++ if (!ec)
++ {
++ log<level::ERR>(
++ "Unable to remove image on processing failure",
++ entry("ERROR=%s", ec.message().c_str()),
++ entry("IMAGE=%s", tarballPath.c_str()));
++ }
+ }
+ }
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager_%.bbappend b/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager_%.bbappend
index ae108bf70..623c4f77e 100644
--- a/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager_%.bbappend
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager_%.bbappend
@@ -12,12 +12,13 @@ SRC_URI += "file://0001-Add-more-error-types.patch \
file://0006-Modify-the-ID-of-software-image-updater-object-on-DB.patch \
file://0007-Adding-StandBySpare-for-firmware-activation.patch \
file://0008-item_updater-update-the-bmc_active-objectPath.patch \
+ file://0009-Add-ApplyOptions-D-bus-property-under-Software.patch \
file://0011-Fix-for-RedudancyPriority-in-item_updater.patch \
+ file://0013-remove-image-file-on-pre-script-failures.patch \
"
SRC_URI_PFR = "file://0007-PFR-images-support.patch \
file://0008-PFR-image-HASH-verification.patch \
- file://0009-Add-ApplyOptions-D-bus-property-under-Software.patch \
file://0010-Add-error-reporting-to-pfr_image_manager.patch \
"
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0004-Remove-QueryString.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0004-Remove-QueryString.patch
new file mode 100644
index 000000000..238fb83c7
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0004-Remove-QueryString.patch
@@ -0,0 +1,621 @@
+From f8749b5898403ee04a623a5bc534bd939865e221 Mon Sep 17 00:00:00 2001
+From: James Feist <james.feist@linux.intel.com>
+Date: Wed, 22 Jul 2020 09:08:38 -0700
+Subject: [PATCH 1/1] Remove QueryString
+
+QueryString is an error-prone library that was
+leftover from crow. Replace it with boost::url,
+a header only library based and written by the
+one of the authors of boost beast.
+
+Tested: Verified logging paging still worked
+as expected
+
+Change-Id: I47c225089aa7d0f7d2299142f91806294f879381
+Signed-off-by: James Feist <james.feist@linux.intel.com>
+---
+ CMakeLists.txt | 2 +
+ CMakeLists.txt.in | 10 +
+ http/http_connection.h | 21 +-
+ http/http_request.h | 5 +-
+ http/query_string.h | 421 -----------------------------
+ redfish-core/lib/event_service.hpp | 7 +-
+ redfish-core/lib/log_services.hpp | 20 +-
+ 7 files changed, 45 insertions(+), 441 deletions(-)
+ delete mode 100644 http/query_string.h
+
+diff --git a/CMakeLists.txt b/CMakeLists.txt
+index 2886438..50483ad 100644
+--- a/CMakeLists.txt
++++ b/CMakeLists.txt
+@@ -280,6 +280,8 @@ add_definitions (-DBOOST_ALL_NO_LIB)
+ add_definitions (-DBOOST_NO_RTTI)
+ add_definitions (-DBOOST_NO_TYPEID)
+ add_definitions (-DBOOST_COROUTINES_NO_DEPRECATION_WARNING)
++add_definitions (-DBOOST_URL_STANDALONE)
++add_definitions (-DBOOST_URL_HEADER_ONLY)
+
+ # sdbusplus
+ if (NOT ${YOCTO_DEPENDENCIES})
+diff --git a/CMakeLists.txt.in b/CMakeLists.txt.in
+index d14910f..5cd73f6 100644
+--- a/CMakeLists.txt.in
++++ b/CMakeLists.txt.in
+@@ -53,3 +53,13 @@ externalproject_add (
+ cp -r "${CMAKE_BINARY_DIR}/nlohmann-json-src/include/nlohmann"
+ "${CMAKE_BINARY_DIR}/prefix/include"
+ )
++
++externalproject_add (
++ Boost-URL GIT_REPOSITORY "https://github.com/CPPAlliance/url.git" GIT_TAG
++ a56ae0df6d3078319755fbaa67822b4fa7fd352b SOURCE_DIR
++ "${CMAKE_BINARY_DIR}/boost-url-src" BINARY_DIR
++ "${CMAKE_BINARY_DIR}/boost-url-build" CONFIGURE_COMMAND "" BUILD_COMMAND
++ "" INSTALL_COMMAND mkdir -p "${CMAKE_BINARY_DIR}/prefix/include" &&
++ cp -r "${CMAKE_BINARY_DIR}/boost-url-src/include/boost"
++ "${CMAKE_BINARY_DIR}/prefix/include"
++)
+diff --git a/http/http_connection.h b/http/http_connection.h
+index 35bf99c..8dba3d6 100644
+--- a/http/http_connection.h
++++ b/http/http_connection.h
+@@ -728,13 +728,9 @@ class Connection :
+ return;
+ }
+
+- // Compute the url parameters for the request
+- req->url = req->target();
+- std::size_t index = req->url.find("?");
+- if (index != std::string_view::npos)
+- {
+- req->url = req->url.substr(0, index);
+- }
++ req->urlView = boost::urls::url_view(req->target());
++ req->url = req->urlView.encoded_path();
++
+ crow::authorization::authenticate(*req, res, session);
+
+ bool loggedIn = req && req->session;
+@@ -743,7 +739,16 @@ class Connection :
+ startDeadline(loggedInAttempts);
+ BMCWEB_LOG_DEBUG << "Starting slow deadline";
+
+- req->urlParams = QueryString(std::string(req->target()));
++ req->urlParams = req->urlView.params();
++
++#ifdef BMCWEB_ENABLE_DEBUG
++ std::string paramList = "";
++ for (const auto param : req->urlParams)
++ {
++ paramList += param->key() + " " + param->value() + " ";
++ }
++ BMCWEB_LOG_DEBUG << "QueryParams: " << paramList;
++#endif
+ }
+ else
+ {
+diff --git a/http/http_request.h b/http/http_request.h
+index 0691465..95f88c7 100644
+--- a/http/http_request.h
++++ b/http/http_request.h
+@@ -1,7 +1,6 @@
+ #pragma once
+
+ #include "common.h"
+-#include "query_string.h"
+
+ #include "sessions.hpp"
+
+@@ -9,6 +8,7 @@
+ #include <boost/beast/http.hpp>
+ #include <boost/beast/ssl/ssl_stream.hpp>
+ #include <boost/beast/websocket.hpp>
++#include <boost/url/url_view.hpp>
+
+ namespace crow
+ {
+@@ -24,7 +24,8 @@ struct Request
+ boost::beast::http::request<boost::beast::http::string_body>& req;
+ boost::beast::http::fields& fields;
+ std::string_view url{};
+- QueryString urlParams{};
++ boost::urls::url_view urlView{};
++ boost::urls::url_view::params_type urlParams{};
+ bool isSecure{false};
+
+ const std::string& body;
+diff --git a/http/query_string.h b/http/query_string.h
+deleted file mode 100644
+index e980280..0000000
+--- a/http/query_string.h
++++ /dev/null
+@@ -1,421 +0,0 @@
+-#pragma once
+-
+-#include <cstdio>
+-#include <cstring>
+-#include <iostream>
+-#include <string>
+-#include <vector>
+-
+-namespace crow
+-{
+-// ----------------------------------------------------------------------------
+-// qs_parse (modified)
+-// https://github.com/bartgrantham/qs_parse
+-// ----------------------------------------------------------------------------
+-/* Similar to strncmp, but handles URL-encoding for either string */
+-int qsStrncmp(const char* s, const char* qs, size_t n);
+-
+-/* Finds the beginning of each key/value pair and stores a pointer in qs_kv.
+- * Also decodes the value portion of the k/v pair *in-place*. In a future
+- * enhancement it will also have a compile-time option of sorting qs_kv
+- * alphabetically by key. */
+-size_t qsParse(char* qs, char* qs_kv[], size_t qs_kv_size);
+-
+-/* Used by qs_parse to decode the value portion of a k/v pair */
+-int qsDecode(char* qs);
+-
+-/* Looks up the value according to the key on a pre-processed query string
+- * A future enhancement will be a compile-time option to look up the key
+- * in a pre-sorted qs_kv array via a binary search. */
+-// char * qs_k2v(const char * key, char * qs_kv[], int qs_kv_size);
+-char* qsK2v(const char* key, char* const* qs_kv, int qs_kv_size, int nth);
+-
+-/* Non-destructive lookup of value, based on key. User provides the
+- * destinaton string and length. */
+-char* qsScanvalue(const char* key, const char* qs, char* val, size_t val_len);
+-
+-// TODO: implement sorting of the qs_kv array; for now ensure it's not compiled
+-#undef _qsSORTING
+-
+-// isxdigit _is_ available in <ctype.h>, but let's avoid another header instead
+-#define BMCWEB_QS_ISHEX(x) \
+- ((((x) >= '0' && (x) <= '9') || ((x) >= 'A' && (x) <= 'F') || \
+- ((x) >= 'a' && (x) <= 'f')) \
+- ? 1 \
+- : 0)
+-#define BMCWEB_QS_HEX2DEC(x) \
+- (((x) >= '0' && (x) <= '9') \
+- ? (x)-48 \
+- : ((x) >= 'A' && (x) <= 'F') \
+- ? (x)-55 \
+- : ((x) >= 'a' && (x) <= 'f') ? (x)-87 : 0)
+-#define BMCWEB_QS_ISQSCHR(x) \
+- ((((x) == '=') || ((x) == '#') || ((x) == '&') || ((x) == '\0')) ? 0 : 1)
+-
+-inline int qsStrncmp(const char* s, const char* qs, size_t n)
+-{
+- int i = 0;
+- char u1, u2;
+- char unyb, lnyb;
+-
+- while (n-- > 0)
+- {
+- u1 = *s++;
+- u2 = *qs++;
+-
+- if (!BMCWEB_QS_ISQSCHR(u1))
+- {
+- u1 = '\0';
+- }
+- if (!BMCWEB_QS_ISQSCHR(u2))
+- {
+- u2 = '\0';
+- }
+-
+- if (u1 == '+')
+- {
+- u1 = ' ';
+- }
+- if (u1 == '%') // easier/safer than scanf
+- {
+- unyb = static_cast<char>(*s++);
+- lnyb = static_cast<char>(*s++);
+- if (BMCWEB_QS_ISHEX(unyb) && BMCWEB_QS_ISHEX(lnyb))
+- {
+- u1 = static_cast<char>((BMCWEB_QS_HEX2DEC(unyb) * 16) +
+- BMCWEB_QS_HEX2DEC(lnyb));
+- }
+- else
+- {
+- u1 = '\0';
+- }
+- }
+-
+- if (u2 == '+')
+- {
+- u2 = ' ';
+- }
+- if (u2 == '%') // easier/safer than scanf
+- {
+- unyb = static_cast<char>(*qs++);
+- lnyb = static_cast<char>(*qs++);
+- if (BMCWEB_QS_ISHEX(unyb) && BMCWEB_QS_ISHEX(lnyb))
+- {
+- u2 = static_cast<char>((BMCWEB_QS_HEX2DEC(unyb) * 16) +
+- BMCWEB_QS_HEX2DEC(lnyb));
+- }
+- else
+- {
+- u2 = '\0';
+- }
+- }
+-
+- if (u1 != u2)
+- {
+- return u1 - u2;
+- }
+- if (u1 == '\0')
+- {
+- return 0;
+- }
+- i++;
+- }
+- if (BMCWEB_QS_ISQSCHR(*qs))
+- {
+- return -1;
+- }
+- else
+- {
+- return 0;
+- }
+-}
+-
+-inline size_t qsParse(char* qs, char* qs_kv[], size_t qs_kv_size)
+-{
+- size_t i;
+- size_t j;
+- char* substrPtr;
+-
+- for (i = 0; i < qs_kv_size; i++)
+- {
+- qs_kv[i] = nullptr;
+- }
+-
+- // find the beginning of the k/v substrings or the fragment
+- substrPtr = qs + strcspn(qs, "?#");
+- if (substrPtr[0] != '\0')
+- {
+- substrPtr++;
+- }
+- else
+- {
+- return 0; // no query or fragment
+- }
+-
+- i = 0;
+- while (i < qs_kv_size)
+- {
+- qs_kv[i++] = substrPtr;
+- j = strcspn(substrPtr, "&");
+- if (substrPtr[j] == '\0')
+- {
+- break;
+- }
+- substrPtr += j + 1;
+- }
+-
+- // we only decode the values in place, the keys could have '='s in them
+- // which will hose our ability to distinguish keys from values later
+- for (j = 0; j < i; j++)
+- {
+- substrPtr = qs_kv[j] + strcspn(qs_kv[j], "=&#");
+- if (substrPtr[0] == '&' || substrPtr[0] == '\0')
+- { // blank value: skip decoding
+- substrPtr[0] = '\0';
+- }
+- else
+- {
+- qsDecode(++substrPtr);
+- }
+- }
+-
+-#ifdef _qsSORTING
+-// TODO: qsort qs_kv, using qs_strncmp() for the comparison
+-#endif
+-
+- return i;
+-}
+-
+-inline int qsDecode(char* qs)
+-{
+- int i = 0, j = 0;
+-
+- while (BMCWEB_QS_ISQSCHR(qs[j]))
+- {
+- if (qs[j] == '+')
+- {
+- qs[i] = ' ';
+- }
+- else if (qs[j] == '%') // easier/safer than scanf
+- {
+- if (!BMCWEB_QS_ISHEX(qs[j + 1]) || !BMCWEB_QS_ISHEX(qs[j + 2]))
+- {
+- qs[i] = '\0';
+- return i;
+- }
+- qs[i] = static_cast<char>((BMCWEB_QS_HEX2DEC(qs[j + 1]) * 16) +
+- BMCWEB_QS_HEX2DEC(qs[j + 2]));
+- j += 2;
+- }
+- else
+- {
+- qs[i] = qs[j];
+- }
+- i++;
+- j++;
+- }
+- qs[i] = '\0';
+-
+- return i;
+-}
+-
+-inline char* qsK2v(const char* key, char* const* qs_kv, int qs_kv_size,
+- int nth = 0)
+-{
+- int i;
+- size_t keyLen, skip;
+-
+- keyLen = strlen(key);
+-
+-#ifdef _qsSORTING
+-// TODO: binary search for key in the sorted qs_kv
+-#else // _qsSORTING
+- for (i = 0; i < qs_kv_size; i++)
+- {
+- // we rely on the unambiguous '=' to find the value in our k/v pair
+- if (qsStrncmp(key, qs_kv[i], keyLen) == 0)
+- {
+- skip = strcspn(qs_kv[i], "=");
+- if (qs_kv[i][skip] == '=')
+- {
+- skip++;
+- }
+- // return (zero-char value) ? ptr to trailing '\0' : ptr to value
+- if (nth == 0)
+- {
+- return qs_kv[i] + skip;
+- }
+- else
+- {
+- --nth;
+- }
+- }
+- }
+-#endif // _qsSORTING
+-
+- return nullptr;
+-}
+-
+-inline char* qsScanvalue(const char* key, const char* qs, char* val,
+- size_t val_len)
+-{
+- size_t i, keyLen;
+- const char* tmp;
+-
+- // find the beginning of the k/v substrings
+- if ((tmp = strchr(qs, '?')) != nullptr)
+- {
+- qs = tmp + 1;
+- }
+-
+- keyLen = strlen(key);
+- while (qs[0] != '#' && qs[0] != '\0')
+- {
+- if (qsStrncmp(key, qs, keyLen) == 0)
+- {
+- break;
+- }
+- qs += strcspn(qs, "&") + 1;
+- }
+-
+- if (qs[0] == '\0')
+- {
+- return nullptr;
+- }
+-
+- qs += strcspn(qs, "=&#");
+- if (qs[0] == '=')
+- {
+- qs++;
+- i = strcspn(qs, "&=#");
+- strncpy(val, qs, (val_len - 1) < (i + 1) ? (val_len - 1) : (i + 1));
+- qsDecode(val);
+- }
+- else
+- {
+- if (val_len > 0)
+- {
+- val[0] = '\0';
+- }
+- }
+-
+- return val;
+-}
+-} // namespace crow
+-// ----------------------------------------------------------------------------
+-
+-namespace crow
+-{
+-class QueryString
+-{
+- public:
+- static const size_t maxKeyValuePairsCount = 256;
+-
+- QueryString() = default;
+-
+- QueryString(const QueryString& qs) : url(qs.url)
+- {
+- for (auto p : qs.keyValuePairs)
+- {
+- keyValuePairs.push_back(
+- const_cast<char*>(p - qs.url.c_str() + url.c_str()));
+- }
+- }
+-
+- QueryString& operator=(const QueryString& qs)
+- {
+- if (this == &qs)
+- {
+- return *this;
+- }
+-
+- url = qs.url;
+- keyValuePairs.clear();
+- for (auto p : qs.keyValuePairs)
+- {
+- keyValuePairs.push_back(
+- const_cast<char*>(p - qs.url.c_str() + url.c_str()));
+- }
+- return *this;
+- }
+-
+- QueryString& operator=(QueryString&& qs)
+- {
+- keyValuePairs = std::move(qs.keyValuePairs);
+- auto* oldData = const_cast<char*>(qs.url.c_str());
+- url = std::move(qs.url);
+- for (auto& p : keyValuePairs)
+- {
+- p += const_cast<char*>(url.c_str()) - oldData;
+- }
+- return *this;
+- }
+-
+- explicit QueryString(std::string newUrl) : url(std::move(newUrl))
+- {
+- if (url.empty())
+- {
+- return;
+- }
+-
+- keyValuePairs.resize(maxKeyValuePairsCount);
+-
+- size_t count =
+- qsParse(&url[0], &keyValuePairs[0], maxKeyValuePairsCount);
+- keyValuePairs.resize(count);
+- }
+-
+- void clear()
+- {
+- keyValuePairs.clear();
+- url.clear();
+- }
+-
+- friend std::ostream& operator<<(std::ostream& os, const QueryString& qs)
+- {
+- os << "[ ";
+- for (size_t i = 0; i < qs.keyValuePairs.size(); ++i)
+- {
+- if (i != 0u)
+- {
+- os << ", ";
+- }
+- os << qs.keyValuePairs[i];
+- }
+- os << " ]";
+- return os;
+- }
+-
+- char* get(const std::string& name) const
+- {
+- char* ret = qsK2v(name.c_str(), keyValuePairs.data(),
+- static_cast<int>(keyValuePairs.size()));
+- return ret;
+- }
+-
+- std::vector<char*> getList(const std::string& name) const
+- {
+- std::vector<char*> ret;
+- std::string plus = name + "[]";
+- char* element = nullptr;
+-
+- int count = 0;
+- while (true)
+- {
+- element = qsK2v(plus.c_str(), keyValuePairs.data(),
+- static_cast<int>(keyValuePairs.size()), count++);
+- if (element == nullptr)
+- {
+- break;
+- }
+- ret.push_back(element);
+- }
+- return ret;
+- }
+-
+- private:
+- std::string url;
+- std::vector<char*> keyValuePairs;
+-};
+-
+-} // namespace crow
+diff --git a/redfish-core/lib/event_service.hpp b/redfish-core/lib/event_service.hpp
+index b27c6e0..8bd30f5 100644
+--- a/redfish-core/lib/event_service.hpp
++++ b/redfish-core/lib/event_service.hpp
+@@ -445,13 +445,16 @@ class EventServiceSSE : public Node
+ subValue->protocol = "Redfish";
+ subValue->retryPolicy = "TerminateAfterRetries";
+
+- char* filters = req.urlParams.get("$filter");
+- if (filters == nullptr)
++ boost::urls::url_view::params_type::iterator it =
++ req.urlParams.find("$filter");
++ if (it == req.urlParams.end())
+ {
+ subValue->eventFormatType = "Event";
+ }
++
+ else
+ {
++ std::string filters = it->value();
+ // Reading from query params.
+ bool status = readSSEQueryParams(
+ filters, subValue->eventFormatType, subValue->registryMsgIds,
+diff --git a/redfish-core/lib/log_services.hpp b/redfish-core/lib/log_services.hpp
+index bee1a92..590243c 100644
+--- a/redfish-core/lib/log_services.hpp
++++ b/redfish-core/lib/log_services.hpp
+@@ -218,12 +218,14 @@ static bool getEntryTimestamp(sd_journal* journal, std::string& entryTimestamp)
+ static bool getSkipParam(crow::Response& res, const crow::Request& req,
+ uint64_t& skip)
+ {
+- char* skipParam = req.urlParams.get("$skip");
+- if (skipParam != nullptr)
++ boost::urls::url_view::params_type::iterator it =
++ req.urlParams.find("$skip");
++ if (it != req.urlParams.end())
+ {
++ std::string skipParam = it->value();
+ char* ptr = nullptr;
+- skip = std::strtoul(skipParam, &ptr, 10);
+- if (*skipParam == '\0' || *ptr != '\0')
++ skip = std::strtoul(skipParam.c_str(), &ptr, 10);
++ if (skipParam.empty() || *ptr != '\0')
+ {
+
+ messages::queryParameterValueTypeError(res, std::string(skipParam),
+@@ -238,12 +240,14 @@ static constexpr const uint64_t maxEntriesPerPage = 1000;
+ static bool getTopParam(crow::Response& res, const crow::Request& req,
+ uint64_t& top)
+ {
+- char* topParam = req.urlParams.get("$top");
+- if (topParam != nullptr)
++ boost::urls::url_view::params_type::iterator it =
++ req.urlParams.find("$top");
++ if (it != req.urlParams.end())
+ {
++ std::string topParam = it->value();
+ char* ptr = nullptr;
+- top = std::strtoul(topParam, &ptr, 10);
+- if (*topParam == '\0' || *ptr != '\0')
++ top = std::strtoul(topParam.c_str(), &ptr, 10);
++ if (topParam.empty() || *ptr != '\0')
+ {
+ messages::queryParameterValueTypeError(res, std::string(topParam),
+ "$top");
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0004-bmcweb-handle-device-or-resource-busy-exception.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0004-bmcweb-handle-device-or-resource-busy-exception.patch
new file mode 100644
index 000000000..761caabb7
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0004-bmcweb-handle-device-or-resource-busy-exception.patch
@@ -0,0 +1,219 @@
+From 5fa2fb4bd766b9c74b9edff4701408a002466b2a Mon Sep 17 00:00:00 2001
+From: Karol Wachowski <karol.wachowski@intel.com>
+Date: Fri, 10 Jul 2020 09:54:06 +0000
+Subject: [PATCH] bmcweb handle device or resource busy exception
+
+Use async_method_call_timed() for mount/unmount dbus oprations.
+Long mount/unmount times are supported by VirtualMedia service,
+this works because of settable timeout property, available for each block
+device.
+Default dbus calls will timeout when mount/unmount timeout is long enough.
+
+Get mount/unmount timeout property and use it for mount/unmount calls.
+Add handling of device or resource busy exception (EBUSY) that
+can be thrown by VirtualMedia service during Mount/Unmount dbus operations.
+
+Tested: Verified that after mounting non-existing HTTPS resource
+ in proxy mode, VirtualMedia recovers restoring ready state
+ and returns EBUSY during that transition.
+ Verfied that resources can be mounted/unmounted in both legacy
+ and proxy mode.
+Signed-off-by: Karol Wachowski <karol.wachowski@intel.com>
+Change-Id: Ica62c34db0cce24c4c6169fc661edfde49e948d0
+---
+ redfish-core/lib/virtual_media.hpp | 144 ++++++++++++++++++++++-------
+ 1 file changed, 110 insertions(+), 34 deletions(-)
+
+diff --git a/redfish-core/lib/virtual_media.hpp b/redfish-core/lib/virtual_media.hpp
+index 0b5eb1a..a0c63ad 100644
+--- a/redfish-core/lib/virtual_media.hpp
++++ b/redfish-core/lib/virtual_media.hpp
+@@ -23,6 +23,8 @@
+ // for GetObjectType and ManagedObjectType
+ #include <account_service.hpp>
+
++#include <chrono>
++
+ namespace redfish
+
+ {
+@@ -109,6 +111,26 @@ static void vmParseInterfaceObject(const DbusInterfaceType& interface,
+ }
+ }
+
++/**
++ * @brief parses Timeout property and converts to microseconds
++ */
++static std::optional<uint64_t>
++ vmParseTimeoutProperty(const std::variant<int>& timeoutProperty)
++{
++ const int* timeoutValue = std::get_if<int>(&timeoutProperty);
++ if (timeoutValue)
++ {
++ constexpr int timeoutMarginSeconds = 10;
++ return std::chrono::duration_cast<std::chrono::microseconds>(
++ std::chrono::seconds(*timeoutValue + timeoutMarginSeconds))
++ .count();
++ }
++ else
++ {
++ return std::nullopt;
++ }
++}
++
+ /**
+ * @brief Fill template for Virtual Media Item.
+ */
+@@ -806,22 +828,54 @@ class VirtualMediaActionInsertMedia : public Node
+ }
+
+ crow::connections::systemBus->async_method_call(
+- [asyncResp, secretPipe](const boost::system::error_code ec,
+- bool success) {
++ [asyncResp, service, name, imageUrl, rw, unixFd,
++ secretPipe](const boost::system::error_code ec,
++ const std::variant<int> timeoutProperty) {
+ if (ec)
+ {
+ BMCWEB_LOG_ERROR << "Bad D-Bus request error: " << ec;
+ messages::internalError(asyncResp->res);
++ return;
+ }
+- else if (!success)
++
++ auto timeout = vmParseTimeoutProperty(timeoutProperty);
++ if (timeout == std::nullopt)
+ {
+- BMCWEB_LOG_ERROR << "Service responded with error";
+- messages::generalError(asyncResp->res);
++ BMCWEB_LOG_ERROR << "Timeout property is empty.";
++ messages::internalError(asyncResp->res);
++ return;
+ }
++
++ crow::connections::systemBus->async_method_call_timed(
++ [asyncResp, secretPipe](const boost::system::error_code ec,
++ bool success) {
++ if (ec)
++ {
++ BMCWEB_LOG_ERROR << "Bad D-Bus request error: "
++ << ec;
++ if (ec ==
++ boost::system::errc::device_or_resource_busy)
++ {
++ messages::resourceInUse(asyncResp->res);
++ }
++ else
++ {
++ messages::internalError(asyncResp->res);
++ }
++ }
++ else if (!success)
++ {
++ BMCWEB_LOG_ERROR << "Service responded with error";
++ messages::generalError(asyncResp->res);
++ }
++ },
++ service, "/xyz/openbmc_project/VirtualMedia/Legacy/" + name,
++ "xyz.openbmc_project.VirtualMedia.Legacy", "Mount",
++ *timeout, imageUrl, rw, unixFd);
+ },
+ service, "/xyz/openbmc_project/VirtualMedia/Legacy/" + name,
+- "xyz.openbmc_project.VirtualMedia.Legacy", "Mount", imageUrl, rw,
+- unixFd);
++ "org.freedesktop.DBus.Properties", "Get",
++ "xyz.openbmc_project.VirtualMedia.MountPoint", "Timeout");
+ }
+ };
+
+@@ -955,38 +1009,60 @@ class VirtualMediaActionEjectMedia : public Node
+ const std::string& service, const std::string& name,
+ bool legacy)
+ {
+-
+- // Legacy mount requires parameter with image
++ std::string objectPath = "/xyz/openbmc_project/VirtualMedia/";
++ std::string ifaceName = "xyz.openbmc_project.VirtualMedia";
+ if (legacy)
+ {
+- crow::connections::systemBus->async_method_call(
+- [asyncResp](const boost::system::error_code ec) {
+- if (ec)
+- {
+- BMCWEB_LOG_ERROR << "Bad D-Bus request error: " << ec;
+-
+- messages::internalError(asyncResp->res);
+- return;
+- }
+- },
+- service, "/xyz/openbmc_project/VirtualMedia/Legacy/" + name,
+- "xyz.openbmc_project.VirtualMedia.Legacy", "Unmount");
++ objectPath += "Legacy/";
++ ifaceName += ".Legacy";
+ }
+- else // proxy
++ else
+ {
+- crow::connections::systemBus->async_method_call(
+- [asyncResp](const boost::system::error_code ec) {
+- if (ec)
+- {
+- BMCWEB_LOG_ERROR << "Bad D-Bus request error: " << ec;
+-
+- messages::internalError(asyncResp->res);
+- return;
+- }
+- },
+- service, "/xyz/openbmc_project/VirtualMedia/Proxy/" + name,
+- "xyz.openbmc_project.VirtualMedia.Proxy", "Unmount");
++ objectPath += "Proxy/";
++ ifaceName += ".Proxy";
+ }
++ objectPath += name;
++
++ crow::connections::systemBus->async_method_call(
++ [asyncResp, service, name, objectPath,
++ ifaceName](const boost::system::error_code ec,
++ const std::variant<int> timeoutProperty) {
++ if (ec)
++ {
++ BMCWEB_LOG_ERROR << "Bad D-Bus request error: " << ec;
++ messages::internalError(asyncResp->res);
++ return;
++ }
++
++ auto timeout = vmParseTimeoutProperty(timeoutProperty);
++ if (timeout == std::nullopt)
++ {
++ BMCWEB_LOG_ERROR << "Timeout property is empty.";
++ messages::internalError(asyncResp->res);
++ return;
++ }
++ crow::connections::systemBus->async_method_call_timed(
++ [asyncResp](const boost::system::error_code ec) {
++ if (ec)
++ {
++ BMCWEB_LOG_ERROR << "Bad D-Bus request error: "
++ << ec;
++ if (ec ==
++ boost::system::errc::device_or_resource_busy)
++ {
++ messages::resourceInUse(asyncResp->res);
++ }
++ else
++ {
++ messages::internalError(asyncResp->res);
++ }
++ return;
++ }
++ },
++ service, objectPath, ifaceName, "Unmount", *timeout);
++ },
++ service, objectPath, "org.freedesktop.DBus.Properties", "Get",
++ "xyz.openbmc_project.VirtualMedia.MountPoint", "Timeout");
+ }
+ };
+
+--
+2.25.1
+
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
new file mode 100644
index 000000000..274dd044a
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0005-EventService-https-client-support.patch
@@ -0,0 +1,405 @@
+From f388587781c3d874b13b50ad39e8674f0bc08049 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
+
+Add https client support for push style
+eventing. Using this BMC can push the event
+logs/telemetry data to event listener over
+secure http channel.
+
+Tested:
+ - Created subscription with https destination
+ url. Using SubmitTestEvent action set the
+ event and can see event on event listener.
+ - Validator passed.
+
+Change-Id: I44c3918b39baa2eb5fddda9d635f99aa280a422a
+Signed-off-by: AppaRao Puli <apparao.puli@linux.intel.com>
+---
+ http/http_client.hpp | 270 +++++++++++++++++--------
+ redfish-core/include/event_service_manager.hpp | 2 +-
+ 2 files changed, 186 insertions(+), 86 deletions(-)
+
+diff --git a/http/http_client.hpp b/http/http_client.hpp
+index e6a7db1..27d2af3 100644
+--- a/http/http_client.hpp
++++ b/http/http_client.hpp
+@@ -17,6 +17,7 @@
+ #include <boost/asio/strand.hpp>
+ #include <boost/beast/core.hpp>
+ #include <boost/beast/http.hpp>
++#include <boost/beast/ssl.hpp>
+ #include <boost/beast/version.hpp>
+
+ #include <cstdlib>
+@@ -49,7 +50,10 @@ 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::asio::steady_timer timer;
+ boost::beast::flat_buffer buffer;
+ boost::beast::http::request<boost::beast::http::string_body> req;
+@@ -62,14 +66,37 @@ class HttpClient : public std::enable_shared_from_this<HttpClient>
+ std::string host;
+ std::string port;
+ std::string uri;
++ bool useSsl;
+ uint32_t retryCount;
+ uint32_t maxRetryAttempts;
+ uint32_t retryIntervalSecs;
+ std::string retryPolicyAction;
+ bool runningTimer;
+
++ inline boost::beast::tcp_stream& getConn()
++ {
++ if (useSsl)
++ {
++ return (boost::beast::get_lowest_layer(*sslConn));
++ }
++ else
++ {
++ return (*conn);
++ }
++ }
++
+ void doConnect()
+ {
++ 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);
++ }
++
+ if (state == ConnState::connectInProgress)
+ {
+ 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,
++ 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;
++ }
++ BMCWEB_LOG_DEBUG << "Connected to: " << ep;
++ if (self->useSsl)
++ {
++ self->performHandshake();
++ }
++ else
++ {
++ self->state = ConnState::connected;
++ self->checkQueue();
++ }
++ };
++
++ getConn().expires_after(std::chrono::seconds(30));
++ getConn().async_connect(endpoint, std::move(respHandler));
++ }
++
++ void performHandshake()
++ {
++ sslConn->async_handshake(
++ boost::asio::ssl::stream_base::client,
++ [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();
++ return;
++ }
++ self->state = ConnState::connected;
++ BMCWEB_LOG_DEBUG << "SSL Handshake successfull \n";
++
++ 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;
+
+- req.version(static_cast<int>(11)); // HTTP 1.1
++ req = {};
++ res = {};
++
++ req.version(11); // HTTP 1.1
+ req.target(uri);
+ req.method(boost::beast::http::verb::post);
+
+@@ -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 std::size_t& bytesTransferred) {
++ if (ec)
++ {
++ BMCWEB_LOG_ERROR << "sendMessage() failed: " << ec.message();
++ self->state = ConnState::sendFailed;
++ self->doCloseAndCheckQueue();
++ return;
++ }
++ BMCWEB_LOG_DEBUG << "sendMessage() bytes transferred: "
++ << bytesTransferred;
++ boost::ignore_unused(bytesTransferred);
+
+- // Send the HTTP request to the remote host
+- boost::beast::http::async_write(
+- conn, req,
+- [self(shared_from_this())](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->checkQueue();
+- return;
+- }
+- BMCWEB_LOG_DEBUG << "sendMessage() bytes transferred: "
+- << bytesTransferred;
+- boost::ignore_unused(bytesTransferred);
++ self->recvMessage();
++ };
+
+- self->recvMessage();
+- });
++ getConn().expires_after(std::chrono::seconds(30));
++ if (useSsl)
++ {
++ boost::beast::http::async_write(*sslConn, req,
++ std::move(respHandler));
++ }
++ else
++ {
++ boost::beast::http::async_write(*conn, req, std::move(respHandler));
++ }
+ }
+
+ void recvMessage()
+ {
+- // Receive the HTTP response
+- boost::beast::http::async_read(
+- 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 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();
++ 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();
+- });
++ // 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;
++ }
++
++ self->checkQueue();
++ };
++
++ getConn().expires_after(std::chrono::seconds(30));
++ if (useSsl)
++ {
++ boost::beast::http::async_read(*sslConn, buffer, res,
++ std::move(respHandler));
++ }
++ else
++ {
++ boost::beast::http::async_read(*conn, buffer, res,
++ std::move(respHandler));
++ }
+ }
+
+- void doClose()
++ void doCloseAndCheckQueue()
+ {
+ 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)
+ {
+- 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)
++ {
++ BMCWEB_LOG_DEBUG
++ << "doCloseAndCheckQueue(): Connection closed by server.";
++ }
++ else
++ {
++ BMCWEB_LOG_ERROR << "doCloseAndCheckQueue() failed: "
++ << ec.message();
++ }
+ }
++
++ getConn().close();
+ BMCWEB_LOG_DEBUG << "Connection closed gracefully";
++ checkQueue();
++ return;
+ }
+
+ void checkQueue(const bool newRecord = false)
+ {
+ if (requestDataQueue.empty())
+ {
+- // TODO: Having issue in keeping connection alive. So lets close if
+- // nothing to be transferred.
+- doClose();
+-
+ BMCWEB_LOG_DEBUG << "requestDataQueue is empty\n";
+ return;
+ }
+@@ -257,17 +353,20 @@ 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));
+- timer.async_wait([self = shared_from_this()](
+- const boost::system::error_code& ec) {
+- self->runningTimer = false;
+- self->connStateCheck();
+- });
++ timer.async_wait(
++ [self = shared_from_this()](boost::system::error_code) {
++ self->runningTimer = false;
++ self->connStateCheck();
++ });
+ return;
+ }
+ else
+ {
+- // reset retry count.
+- retryCount = 0;
++ if (state == ConnState::idle)
++ {
++ // State idle means, previous attempt is successful.
++ retryCount = 0;
++ }
+ }
+ connStateCheck();
+
+@@ -310,10 +409,11 @@ 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),
+ timer(ioc), subId(id), host(destIP), port(destPort), uri(destUri),
+- retryCount(0), maxRetryAttempts(5),
++ useSsl(inUseSsl), retryCount(0), maxRetryAttempts(5),
+ retryPolicyAction("TerminateAfterRetries"), runningTimer(false)
+ {
+ boost::asio::ip::tcp::resolver resolver(ioc);
+diff --git a/redfish-core/include/event_service_manager.hpp b/redfish-core/include/event_service_manager.hpp
+index 6362112..3ab2605 100644
+--- a/redfish-core/include/event_service_manager.hpp
++++ b/redfish-core/include/event_service_manager.hpp
+@@ -383,7 +383,7 @@ class Subscription
+ {
+ conn = std::make_shared<crow::HttpClient>(
+ crow::connections::systemBus->get_io_context(), id, host, port,
+- path);
++ path, (uriProto == "https" ? true : false));
+ }
+
+ Subscription(const std::shared_ptr<crow::Request::Adaptor>& adaptor) :
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0005-VirtualMedia-fixes-for-Redfish-Service-Validator.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0005-VirtualMedia-fixes-for-Redfish-Service-Validator.patch
new file mode 100644
index 000000000..52ff4e531
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0005-VirtualMedia-fixes-for-Redfish-Service-Validator.patch
@@ -0,0 +1,122 @@
+From 49dc25100ab8a4220f81bc8f9b54808850fe1267 Mon Sep 17 00:00:00 2001
+From: Przemyslaw Czarnowski <przemyslaw.hawrylewicz.czarnowski@intel.com>
+Date: Wed, 8 Jul 2020 15:17:31 +0200
+Subject: [PATCH] VirtualMedia fixes for Redfish Service Validator
+
+Removes all warnings and errors for VirtualMedia
+- rework for OemVirtualMedia
+- minor adjustments for jsons
+
+Tested:
+Redfish Service Validator ran with no errors and/or warnings
+
+Change-Id: Ic027166153a807a8bd3a6c04f042969f16e0dc6a
+Signed-off-by: Przemyslaw Czarnowski <przemyslaw.hawrylewicz.czarnowski@intel.com>
+---
+ redfish-core/lib/virtual_media.hpp | 4 +--
+ .../v1/JsonSchemas/OemVirtualMedia/index.json | 28 +++----------------
+ .../redfish/v1/schema/OemVirtualMedia_v1.xml | 12 ++++----
+ 3 files changed, 12 insertions(+), 32 deletions(-)
+
+diff --git a/redfish-core/lib/virtual_media.hpp b/redfish-core/lib/virtual_media.hpp
+index 552e255..183abbe 100644
+--- a/redfish-core/lib/virtual_media.hpp
++++ b/redfish-core/lib/virtual_media.hpp
+@@ -129,7 +129,7 @@ static nlohmann::json vmItemTemplate(const std::string& name,
+ item["MediaTypes"] = {"CD", "USBStick"};
+ item["TransferMethod"] = "Stream";
+ item["TransferProtocolType"] = nullptr;
+- item["Oem"]["OpenBmc"]["WebSocketEndpoint"] = nullptr;
++ item["Oem"]["OpenBMC"]["WebSocketEndpoint"] = nullptr;
+ item["Oem"]["OpenBMC"]["@odata.type"] =
+ "#OemVirtualMedia.v1_0_0.VirtualMedia";
+
+@@ -1039,7 +1039,7 @@ class VirtualMediaCollection : public Node
+ "#VirtualMediaCollection.VirtualMediaCollection";
+ res.jsonValue["Name"] = "Virtual Media Services";
+ res.jsonValue["@odata.id"] =
+- "/redfish/v1/Managers/" + name + "/VirtualMedia/";
++ "/redfish/v1/Managers/" + name + "/VirtualMedia";
+
+ crow::connections::systemBus->async_method_call(
+ [asyncResp, name](const boost::system::error_code ec,
+diff --git a/static/redfish/v1/JsonSchemas/OemVirtualMedia/index.json b/static/redfish/v1/JsonSchemas/OemVirtualMedia/index.json
+index 78bd8b7..9ae641a 100644
+--- a/static/redfish/v1/JsonSchemas/OemVirtualMedia/index.json
++++ b/static/redfish/v1/JsonSchemas/OemVirtualMedia/index.json
+@@ -3,9 +3,10 @@
+ "$schema": "http://redfish.dmtf.org/schemas/v1/redfish-schema-v1.json",
+ "copyright": "Copyright 2014-2019 DMTF. For the full DMTF copyright policy, see http://www.dmtf.org/about/policies/copyright",
+ "definitions": {
+- "OpenBmc": {
+- "additionalProperties": true,
+- "description": "Oem properties for OpenBmc.",
++ "VirtualMedia": {
++ "additionalProperties": false,
++ "description": "OEM Extension for VirtualMedia",
++ "longDescription": "OEM Extension for VirtualMedia to support Proxy mode.",
+ "patternProperties": {
+ "^([a-zA-Z_][a-zA-Z0-9_]*)?@(odata|Redfish|Message)\\.[a-zA-Z_][a-zA-Z0-9_]*$": {
+ "description": "This property shall specify a valid odata or Redfish property.",
+@@ -32,27 +33,6 @@
+ }
+ },
+ "type": "object"
+- },
+- "VirtualMedia": {
+- "additionalProperties": false,
+- "description": "OEM Extension for VirtualMedia",
+- "longDescription": "OEM Extension for VirtualMedia to support Proxy mode.",
+- "patternProperties": {
+- "^([a-zA-Z_][a-zA-Z0-9_]*)?@(odata|Redfish|Message)\\.[a-zA-Z_][a-zA-Z0-9_]*$": {
+- "description": "This property shall specify a valid odata or Redfish property.",
+- "type": [
+- "array",
+- "boolean",
+- "integer",
+- "number",
+- "null",
+- "object",
+- "string"
+- ]
+- }
+- },
+- "properties": {},
+- "type": "object"
+ }
+ },
+ "owningEntity": "OpenBMC",
+diff --git a/static/redfish/v1/schema/OemVirtualMedia_v1.xml b/static/redfish/v1/schema/OemVirtualMedia_v1.xml
+index 2b03a67..84afe73 100644
+--- a/static/redfish/v1/schema/OemVirtualMedia_v1.xml
++++ b/static/redfish/v1/schema/OemVirtualMedia_v1.xml
+@@ -25,20 +25,20 @@
+ <Annotation Term="Redfish.OwningEntity" String="OpenBMC"/>
+ <Annotation Term="Redfish.Release" String="1.0"/>
+
+- <ComplexType Name="OpenBmc" BaseType="Resource.OemObject">
+- <Annotation Term="OData.AdditionalProperties" Bool="true"/>
+- <Annotation Term="OData.Description" String="Oem properties for OpenBmc." />
+-
+- <Property Name="WebSocketEndpoint" Type="Edm.String">
++ <Property Name="WebSocketEndpoint" Type="Edm.String">
+ <Annotation Term="OData.Permissions" EnumMember="OData.Permission/Read"/>
+ <Annotation Term="OData.Description" String="Indicates endpoint socket name and location."/>
+ <Annotation Term="OData.LongDescription" String="The value of this property shall be a structure ring indicating location and name of the socket used to communicate with nbd server."/>
+ </Property>
+- </ComplexType>
+
+ <EntityType Name="VirtualMedia" BaseType="Resource.OemObject" Abstract="true">
+ <Annotation Term="OData.Description" String="OEM Extension for VirtualMedia"/>
+ <Annotation Term="OData.LongDescription" String="OEM Extension for VirtualMedia to support Proxy mode."/>
++ <Property Name="WebSocketEndpoint" Type="Edm.String">
++ <Annotation Term="OData.Permissions" EnumMember="OData.Permission/Read"/>
++ <Annotation Term="OData.Description" String="Indicates endpoint socket name and location."/>
++ <Annotation Term="OData.LongDescription" String="The value of this property shall be a structure ring indicating location and name of the socket used to communicate with nbd server."/>
++ </Property>
+ </EntityType>
+ </Schema>
+
+--
+2.25.0
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0006-Fix-Image-and-ImageName-values-in-schema.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0006-Fix-Image-and-ImageName-values-in-schema.patch
new file mode 100644
index 000000000..c182822a6
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0006-Fix-Image-and-ImageName-values-in-schema.patch
@@ -0,0 +1,38 @@
+From 15305d3a9db371af924482e5a6959bbf7812cf6c Mon Sep 17 00:00:00 2001
+From: Przemyslaw Czarnowski <przemyslaw.hawrylewicz.czarnowski@intel.com>
+Date: Wed, 29 Jul 2020 15:56:57 +0200
+Subject: [PATCH] Fix Image and ImageName values in schema
+
+According to design document and schema Image shall contain URL of
+image location and ImageName only name of the image.
+
+Change-Id: Ie1a906c66aa2a10113c307eb1e7d2d7da2810fbd
+Signed-off-by: Przemyslaw Czarnowski <przemyslaw.hawrylewicz.czarnowski@intel.com>
+---
+ redfish-core/lib/virtual_media.hpp | 10 +++++++++-
+ 1 file changed, 9 insertions(+), 1 deletion(-)
+
+diff --git a/redfish-core/lib/virtual_media.hpp b/redfish-core/lib/virtual_media.hpp
+index 183abbe..0345e7b 100644
+--- a/redfish-core/lib/virtual_media.hpp
++++ b/redfish-core/lib/virtual_media.hpp
+@@ -97,7 +97,15 @@ static void vmParseInterfaceObject(const DbusInterfaceType& interface,
+ std::get_if<std::string>(&imageUrlProperty->second);
+ if (imageUrlValue && !imageUrlValue->empty())
+ {
+- aResp->res.jsonValue["ImageName"] = *imageUrlValue;
++ std::size_t lastIndex = imageUrlValue->rfind("/");
++ if (lastIndex == std::string::npos)
++ {
++ aResp->res.jsonValue["ImageName"] = *imageUrlValue;
++ }
++
++ aResp->res.jsonValue["ImageName"] =
++ imageUrlValue->substr(lastIndex + 1);
++ aResp->res.jsonValue["Image"] = *imageUrlValue;
+ aResp->res.jsonValue["Inserted"] = *activeValue;
+ if (*activeValue == true)
+ {
+--
+2.25.0
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0001-Redfish-TelemetryService-schema-implementation.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0001-Redfish-TelemetryService-schema-implementation.patch
new file mode 100644
index 000000000..3850c8fa8
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0001-Redfish-TelemetryService-schema-implementation.patch
@@ -0,0 +1,913 @@
+From 7820421433349df28bd393e8d610d1848af0f1c8 Mon Sep 17 00:00:00 2001
+From: "Wludzik, Jozef" <jozef.wludzik@intel.com>
+Date: Mon, 27 Apr 2020 17:24:15 +0200
+Subject: [PATCH 1/5] Redfish TelemetryService schema implementation
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Added TelemetryService, MetricReports, MetricReportCollection,
+MetricReportDefinition and MetricReportDefinitionCollection schemas
+with GET method support. Added TelemetryService URI to root service.
+Implemented communication with backend - MonitoringService.
+Added schemes attributes that are supported by MonitoringService
+design. User is able to fetch basic information about reports if
+MonitoringService is present in OpenBMC.
+
+Tested:
+ - Succesfully passed RedfishServiceValidator.py
+ - Validated conversion to duration format using whole
+ range of uint32_t type
+ - Validated assigning value to JSON response using different
+ closures and std::functions types
+
+Signed-off-by: Wludzik, Jozef <jozef.wludzik@intel.com>
+Signed-off-by: Adrian Ambrożewicz <adrian.ambrozewicz@linux.intel.com>
+Change-Id: Ie6b0b49f4ef5eeaef07d1209b6c349270c04d570
+---
+ include/dbus_utility.hpp | 21 +++
+ redfish-core/include/redfish.hpp | 10 ++
+ redfish-core/include/utils/json_utils.hpp | 101 +++++++++++++
+ redfish-core/include/utils/telemetry_utils.hpp | 100 +++++++++++++
+ redfish-core/include/utils/time_utils.hpp | 97 +++++++++++++
+ redfish-core/lib/metric_report.hpp | 149 +++++++++++++++++++
+ redfish-core/lib/metric_report_definition.hpp | 193 +++++++++++++++++++++++++
+ redfish-core/lib/service_root.hpp | 2 +
+ redfish-core/lib/telemetry_service.hpp | 92 ++++++++++++
+ 9 files changed, 765 insertions(+)
+ create mode 100644 redfish-core/include/utils/telemetry_utils.hpp
+ create mode 100644 redfish-core/include/utils/time_utils.hpp
+ create mode 100644 redfish-core/lib/metric_report.hpp
+ create mode 100644 redfish-core/lib/metric_report_definition.hpp
+ create mode 100644 redfish-core/lib/telemetry_service.hpp
+
+diff --git a/include/dbus_utility.hpp b/include/dbus_utility.hpp
+index e1360f7..3df88d8 100644
+--- a/include/dbus_utility.hpp
++++ b/include/dbus_utility.hpp
+@@ -109,5 +109,26 @@ inline void checkDbusPathExists(const std::string& path, Callback&& callback)
+ std::array<std::string, 0>());
+ }
+
++template <typename Array, typename Callback>
++inline void getSubTreePaths(Callback&& callback, const std::string& path,
++ int depth, Array& interfaces)
++{
++ crow::connections::systemBus->async_method_call(
++ callback, "xyz.openbmc_project.ObjectMapper",
++ "/xyz/openbmc_project/object_mapper",
++ "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", path, depth,
++ interfaces);
++}
++
++template <typename Callback>
++inline void getAllProperties(Callback&& callback, const std::string& service,
++ const std::string& path,
++ const std::string& interface)
++{
++ crow::connections::systemBus->async_method_call(
++ callback, service, path, "org.freedesktop.DBus.Properties", "GetAll",
++ interface);
++}
++
+ } // namespace utility
+ } // namespace dbus
+diff --git a/redfish-core/include/redfish.hpp b/redfish-core/include/redfish.hpp
+index cc98e1a..3d4c117 100644
+--- a/redfish-core/include/redfish.hpp
++++ b/redfish-core/include/redfish.hpp
+@@ -25,6 +25,8 @@
+ #include "../lib/log_services.hpp"
+ #include "../lib/managers.hpp"
+ #include "../lib/message_registries.hpp"
++#include "../lib/metric_report.hpp"
++#include "../lib/metric_report_definition.hpp"
+ #include "../lib/network_protocol.hpp"
+ #include "../lib/pcie.hpp"
+ #include "../lib/power.hpp"
+@@ -35,6 +37,7 @@
+ #include "../lib/storage.hpp"
+ #include "../lib/systems.hpp"
+ #include "../lib/task.hpp"
++#include "../lib/telemetry_service.hpp"
+ #include "../lib/thermal.hpp"
+ #include "../lib/update_service.hpp"
+ #ifdef BMCWEB_ENABLE_VM_NBDPROXY
+@@ -202,6 +205,13 @@ class RedfishService
+ nodes.emplace_back(std::make_unique<HypervisorInterface>(app));
+ nodes.emplace_back(std::make_unique<HypervisorSystem>(app));
+
++ nodes.emplace_back(std::make_unique<TelemetryService>(app));
++ nodes.emplace_back(
++ std::make_unique<MetricReportDefinitionCollection>(app));
++ nodes.emplace_back(std::make_unique<MetricReportDefinition>(app));
++ nodes.emplace_back(std::make_unique<MetricReportCollection>(app));
++ nodes.emplace_back(std::make_unique<MetricReport>(app));
++
+ for (const auto& node : nodes)
+ {
+ node->initPrivileges();
+diff --git a/redfish-core/include/utils/json_utils.hpp b/redfish-core/include/utils/json_utils.hpp
+index d578de4..fbb259d 100644
+--- a/redfish-core/include/utils/json_utils.hpp
++++ b/redfish-core/include/utils/json_utils.hpp
+@@ -13,15 +13,19 @@
+ // See the License for the specific language governing permissions and
+ // limitations under the License.
+ */
++
+ #pragma once
+
+ #include <http_request.h>
+ #include <http_response.h>
+
++#include <boost/container/flat_map.hpp>
+ #include <error_messages.hpp>
+ #include <nlohmann/json.hpp>
+
+ #include <bitset>
++#include <string>
++#include <variant>
+
+ namespace redfish
+ {
+@@ -436,5 +440,102 @@ bool getValueFromJsonObject(nlohmann::json& jsonData, const std::string& key,
+ return details::unpackValue(jsonValue, key, value);
+ }
+
++template <class T>
++struct IsStdFunction
++{
++ static constexpr bool value = false;
++};
++
++template <class T>
++struct IsStdFunction<std::function<T>>
++{
++ static constexpr bool value = true;
++};
++
++template <class T>
++constexpr bool is_std_function_v = IsStdFunction<T>::value;
++
++/**
++ * @brief Assign dbus property to http response attribute if property is stored
++ * on the map.
++ */
++template <typename T, typename S, typename... V>
++bool assignIfPresent(
++ const boost::container::flat_map<std::string, std::variant<V...>>& ret,
++ const char* propertyName, nlohmann::json& attribute, const S& convert)
++{
++ if constexpr (is_std_function_v<S>)
++ {
++ if (!convert)
++ {
++ BMCWEB_LOG_ERROR << "Passed empty target as convert argument";
++ return false;
++ }
++ }
++
++ auto found = ret.find(propertyName);
++ if (found != ret.end())
++ {
++ auto property = std::get_if<T>(&found->second);
++ if (property)
++ {
++ attribute = convert(*property);
++ return true;
++ }
++ else
++ {
++ BMCWEB_LOG_ERROR << "Variant does not contain this type";
++ }
++ }
++ else
++ {
++ BMCWEB_LOG_ERROR << "Element not found in map";
++ }
++
++ return false;
++}
++
++template <typename T, typename... V>
++bool assignIfPresent(
++ const boost::container::flat_map<std::string, std::variant<V...>>& ret,
++ const char* propertyName, nlohmann::json& attribute)
++{
++ return assignIfPresent<T>(ret, propertyName, attribute,
++ [](const T& v) -> T { return v; });
++}
++
++template <typename T, typename... V>
++bool assignIfPresent(
++ const boost::container::flat_map<std::string, std::variant<V...>>& ret,
++ const char* attributeName, crow::Response& res)
++{
++ return assignIfPresent<T>(ret, attributeName, res.jsonValue[attributeName]);
++}
++
++/**
++ * @brief Translate dbusPaths received from ObjectMapper into Redfish
++ * collection members and fill http response with those information.
++ */
++inline void dbusPathsToMembersArray(crow::Response& res,
++ const std::vector<std::string>& reports,
++ const char* path)
++{
++ nlohmann::json& members = res.jsonValue["Members"];
++ members = nlohmann::json::array();
++
++ for (const std::string& objpath : reports)
++ {
++ std::size_t lastPos = objpath.rfind("/");
++ if (lastPos == std::string::npos)
++ {
++ BMCWEB_LOG_ERROR << "Failed to find '/' in " << objpath;
++ continue;
++ }
++ members.push_back({{"@odata.id", path + objpath.substr(lastPos + 1)}});
++ }
++
++ res.jsonValue["Members@odata.count"] = members.size();
++}
++
+ } // namespace json_util
+ } // namespace redfish
+diff --git a/redfish-core/include/utils/telemetry_utils.hpp b/redfish-core/include/utils/telemetry_utils.hpp
+new file mode 100644
+index 0000000..05ed00f
+--- /dev/null
++++ b/redfish-core/include/utils/telemetry_utils.hpp
+@@ -0,0 +1,100 @@
++/*
++// Copyright (c) 2018-2020 Intel Corporation
++//
++// Licensed under the Apache License, Version 2.0 (the "License");
++// you may not use this file except in compliance with the License.
++// You may obtain a copy of the License at
++//
++// http://www.apache.org/licenses/LICENSE-2.0
++//
++// Unless required by applicable law or agreed to in writing, software
++// distributed under the License is distributed on an "AS IS" BASIS,
++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
++// See the License for the specific language governing permissions and
++// limitations under the License.
++*/
++
++#pragma once
++
++namespace redfish
++{
++
++namespace telemetry
++{
++
++static constexpr const char* metricReportDefinitionUri =
++ "/redfish/v1/TelemetryService/MetricReportDefinitions/";
++static constexpr const char* metricReportUri =
++ "/redfish/v1/TelemetryService/MetricReports/";
++static constexpr const char* reportInterface =
++ "xyz.openbmc_project.MonitoringService.Report";
++static constexpr const char* telemetryPath =
++ "/xyz/openbmc_project/MonitoringService/Reports/TelemetryService";
++
++static void getReportCollection(const std::shared_ptr<AsyncResp>& asyncResp,
++ const char* uri)
++{
++ const std::array<const char*, 1> interfaces = {reportInterface};
++
++ dbus::utility::getSubTreePaths(
++ [asyncResp, uri](const boost::system::error_code ec,
++ const std::vector<std::string>& reports) {
++ if (ec == boost::system::errc::no_such_file_or_directory)
++ {
++ asyncResp->res.jsonValue["Members"] = nlohmann::json::array();
++ asyncResp->res.jsonValue["Members@odata.count"] = 0;
++ return;
++ }
++
++ if (ec)
++ {
++ messages::internalError(asyncResp->res);
++ BMCWEB_LOG_ERROR << "respHandler DBus error " << ec;
++ return;
++ }
++
++ json_util::dbusPathsToMembersArray(asyncResp->res, reports, uri);
++ },
++ telemetryPath, 1, interfaces);
++}
++
++template <typename Callback>
++static void getReport(const std::shared_ptr<AsyncResp>& asyncResp,
++ const std::string& id, const char* schemaType,
++ const Callback&& callback)
++{
++ const std::array<const char*, 1> interfaces = {reportInterface};
++
++ dbus::utility::getSubTreePaths(
++ [asyncResp, id, schemaType,
++ callback](const boost::system::error_code ec,
++ const std::vector<std::string>& reports) {
++ if (ec == boost::system::errc::no_such_file_or_directory)
++ {
++ messages::resourceNotFound(asyncResp->res, schemaType, id);
++ return;
++ }
++
++ if (ec)
++ {
++ messages::internalError(asyncResp->res);
++ BMCWEB_LOG_ERROR << "respHandler DBus error " << ec;
++ return;
++ }
++
++ const std::string target = "/xyz/openbmc_project/"
++ "MonitoringService/Reports/"
++ "TelemetryService/" +
++ id;
++ auto path = std::find(reports.begin(), reports.end(), target);
++ if (path == std::end(reports))
++ {
++ messages::resourceNotFound(asyncResp->res, schemaType, id);
++ return;
++ }
++ callback(asyncResp, *path, id);
++ },
++ telemetryPath, 1, interfaces);
++}
++} // namespace telemetry
++} // namespace redfish
+diff --git a/redfish-core/include/utils/time_utils.hpp b/redfish-core/include/utils/time_utils.hpp
+new file mode 100644
+index 0000000..0256b3f
+--- /dev/null
++++ b/redfish-core/include/utils/time_utils.hpp
+@@ -0,0 +1,97 @@
++/*
++// Copyright (c) 2020 Intel Corporation
++//
++// Licensed under the Apache License, Version 2.0 (the "License");
++// you may not use this file except in compliance with the License.
++// You may obtain a copy of the License at
++//
++// http://www.apache.org/licenses/LICENSE-2.0
++//
++// Unless required by applicable law or agreed to in writing, software
++// distributed under the License is distributed on an "AS IS" BASIS,
++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
++// See the License for the specific language governing permissions and
++// limitations under the License.
++*/
++
++#pragma once
++
++#include <boost/algorithm/string/trim.hpp>
++
++#include <chrono>
++#include <cstdint>
++#include <string>
++#include <type_traits>
++
++namespace redfish
++{
++
++namespace time_utils
++{
++
++namespace details
++{
++
++template <typename T>
++std::string toDurationFormatItem(std::chrono::milliseconds& duration,
++ const char* postfix)
++{
++ const auto t = std::chrono::duration_cast<T>(duration);
++ if (t.count() == 0)
++ {
++ return "";
++ }
++
++ std::stringstream ss;
++ if constexpr (std::is_same<T, std::chrono::milliseconds>::value)
++ {
++ ss << static_cast<float>(t.count()) /
++ static_cast<float>(std::chrono::milliseconds::period::den);
++ }
++ else
++ {
++ ss << t.count();
++ }
++ ss << postfix;
++ duration -= t;
++ return ss.str();
++}
++
++} // namespace details
++
++/**
++ * @brief Convert time value into duration format that is based on ISO 8601.
++ * Pattern: "-?P(\\d+D)?(T(\\d+H)?(\\d+M)?(\\d+(.\\d+)?S)?)?"
++ * Reference: "Redfish Telemetry White Paper".
++ */
++std::string toDurationFormat(const uint32_t ms)
++{
++ std::chrono::milliseconds duration(ms);
++ if (duration.count() == 0)
++ {
++ return "PT0S";
++ }
++
++ std::string fmt;
++ fmt.reserve(sizeof("PxxxDTxxHxxMxx.xxxxxxS"));
++
++ using Days = std::chrono::duration<int, std::ratio<24 * 60 * 60>>;
++
++ fmt += "P";
++ fmt += details::toDurationFormatItem<Days>(duration, "D");
++ if (duration.count() == 0)
++ {
++ return fmt;
++ }
++
++ fmt += "T";
++ fmt += details::toDurationFormatItem<std::chrono::hours>(duration, "H");
++ fmt += details::toDurationFormatItem<std::chrono::minutes>(duration, "M");
++ fmt +=
++ details::toDurationFormatItem<std::chrono::milliseconds>(duration, "S");
++
++ return fmt;
++}
++
++} // namespace time_utils
++} // namespace redfish
+diff --git a/redfish-core/lib/metric_report.hpp b/redfish-core/lib/metric_report.hpp
+new file mode 100644
+index 0000000..a52d680
+--- /dev/null
++++ b/redfish-core/lib/metric_report.hpp
+@@ -0,0 +1,149 @@
++/*
++// Copyright (c) 2018-2020 Intel Corporation
++//
++// Licensed under the Apache License, Version 2.0 (the "License");
++// you may not use this file except in compliance with the License.
++// You may obtain a copy of the License at
++//
++// http://www.apache.org/licenses/LICENSE-2.0
++//
++// Unless required by applicable law or agreed to in writing, software
++// distributed under the License is distributed on an "AS IS" BASIS,
++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
++// See the License for the specific language governing permissions and
++// limitations under the License.
++*/
++
++#pragma once
++
++#include "node.hpp"
++#include "utils/telemetry_utils.hpp"
++
++#include <boost/container/flat_map.hpp>
++
++#include <system_error>
++#include <variant>
++
++namespace redfish
++{
++
++class MetricReportCollection : public Node
++{
++ public:
++ MetricReportCollection(CrowApp& app) : Node(app, telemetry::metricReportUri)
++ {
++ entityPrivileges = {
++ {boost::beast::http::verb::get, {{"Login"}}},
++ {boost::beast::http::verb::head, {{"Login"}}},
++ {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
++ {boost::beast::http::verb::put, {{"ConfigureManager"}}},
++ {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
++ {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
++ }
++
++ private:
++ void doGet(crow::Response& res, const crow::Request& req,
++ const std::vector<std::string>& params) override
++ {
++ res.jsonValue["@odata.type"] =
++ "#MetricReportCollection.MetricReportCollection";
++ res.jsonValue["@odata.id"] =
++ "/redfish/v1/TelemetryService/MetricReports";
++ res.jsonValue["Name"] = "Metric Report Collection";
++
++ auto asyncResp = std::make_shared<AsyncResp>(res);
++ telemetry::getReportCollection(asyncResp, telemetry::metricReportUri);
++ }
++};
++
++class MetricReport : public Node
++{
++ public:
++ MetricReport(CrowApp& app) :
++ Node(app, std::string(telemetry::metricReportUri) + "<str>/",
++ std::string())
++ {
++ entityPrivileges = {
++ {boost::beast::http::verb::get, {{"Login"}}},
++ {boost::beast::http::verb::head, {{"Login"}}},
++ {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
++ {boost::beast::http::verb::put, {{"ConfigureManager"}}},
++ {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
++ {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
++ }
++
++ private:
++ void doGet(crow::Response& res, const crow::Request& req,
++ const std::vector<std::string>& params) override
++ {
++ auto asyncResp = std::make_shared<AsyncResp>(res);
++
++ if (params.size() != 1)
++ {
++ messages::internalError(asyncResp->res);
++ return;
++ }
++
++ const std::string& id = params[0];
++ telemetry::getReport(asyncResp, id, schemaType, getReportProperties);
++ }
++
++ using Readings =
++ std::vector<std::tuple<std::string, std::string, double, int32_t>>;
++ using MetricValues = std::vector<std::map<std::string, std::string>>;
++
++ static MetricValues toMetricValues(const Readings& readings)
++ {
++ MetricValues metricValues;
++
++ for (auto& [id, metadata, sensorValue, timestamp] : readings)
++ {
++ metricValues.push_back({
++ {"MetricId", id},
++ {"MetricProperty", metadata},
++ {"MetricValue", std::to_string(sensorValue)},
++ {"Timestamp", crow::utility::getDateTime(timestamp)},
++ });
++ }
++
++ return metricValues;
++ }
++
++ static void getReportProperties(const std::shared_ptr<AsyncResp> asyncResp,
++ const std::string& reportPath,
++ const std::string& id)
++ {
++ asyncResp->res.jsonValue["@odata.type"] = schemaType;
++ asyncResp->res.jsonValue["@odata.id"] = telemetry::metricReportUri + id;
++ asyncResp->res.jsonValue["Id"] = id;
++ asyncResp->res.jsonValue["Name"] = id;
++ asyncResp->res.jsonValue["MetricReportDefinition"]["@odata.id"] =
++ telemetry::metricReportDefinitionUri + id;
++
++ dbus::utility::getAllProperties(
++ [asyncResp](
++ const boost::system::error_code ec,
++ const boost::container::flat_map<
++ std::string, std::variant<Readings, int32_t>>& ret) {
++ if (ec)
++ {
++ messages::internalError(asyncResp->res);
++ BMCWEB_LOG_ERROR << "respHandler DBus error " << ec;
++ return;
++ }
++
++ json_util::assignIfPresent<int32_t>(
++ ret, "Timestamp", asyncResp->res.jsonValue["Timestamp"],
++ crow::utility::getDateTime);
++ json_util::assignIfPresent<Readings>(
++ ret, "Readings", asyncResp->res.jsonValue["MetricValues"],
++ toMetricValues);
++ },
++ "xyz.openbmc_project.MonitoringService", reportPath,
++ "xyz.openbmc_project.MonitoringService.Report");
++ }
++
++ static constexpr const char* schemaType =
++ "#MetricReport.v1_3_0.MetricReport";
++};
++} // namespace redfish
+diff --git a/redfish-core/lib/metric_report_definition.hpp b/redfish-core/lib/metric_report_definition.hpp
+new file mode 100644
+index 0000000..d82ae59
+--- /dev/null
++++ b/redfish-core/lib/metric_report_definition.hpp
+@@ -0,0 +1,193 @@
++/*
++// Copyright (c) 2018-2020 Intel Corporation
++//
++// Licensed under the Apache License, Version 2.0 (the "License");
++// you may not use this file except in compliance with the License.
++// You may obtain a copy of the License at
++//
++// http://www.apache.org/licenses/LICENSE-2.0
++//
++// Unless required by applicable law or agreed to in writing, software
++// distributed under the License is distributed on an "AS IS" BASIS,
++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
++// See the License for the specific language governing permissions and
++// limitations under the License.
++*/
++
++#pragma once
++
++#include "node.hpp"
++#include "utils/telemetry_utils.hpp"
++#include "utils/time_utils.hpp"
++
++#include <boost/container/flat_map.hpp>
++
++#include <system_error>
++#include <variant>
++
++namespace redfish
++{
++
++class MetricReportDefinitionCollection : public Node
++{
++ public:
++ MetricReportDefinitionCollection(CrowApp& app) :
++ Node(app, telemetry::metricReportDefinitionUri)
++ {
++ entityPrivileges = {
++ {boost::beast::http::verb::get, {{"Login"}}},
++ {boost::beast::http::verb::head, {{"Login"}}},
++ {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
++ {boost::beast::http::verb::put, {{"ConfigureManager"}}},
++ {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
++ {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
++ }
++
++ private:
++ void doGet(crow::Response& res, const crow::Request& req,
++ const std::vector<std::string>& params) override
++ {
++ res.jsonValue["@odata.type"] = "#MetricReportDefinitionCollection."
++ "MetricReportDefinitionCollection";
++ res.jsonValue["@odata.id"] =
++ "/redfish/v1/TelemetryService/MetricReportDefinitions";
++ res.jsonValue["Name"] = "Metric Definition Collection";
++
++ auto asyncResp = std::make_shared<AsyncResp>(res);
++ telemetry::getReportCollection(asyncResp,
++ telemetry::metricReportDefinitionUri);
++ }
++};
++
++class MetricReportDefinition : public Node
++{
++ public:
++ MetricReportDefinition(CrowApp& app) :
++ Node(app, std::string(telemetry::metricReportDefinitionUri) + "<str>/",
++ std::string())
++ {
++ entityPrivileges = {
++ {boost::beast::http::verb::get, {{"Login"}}},
++ {boost::beast::http::verb::head, {{"Login"}}},
++ {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
++ {boost::beast::http::verb::put, {{"ConfigureManager"}}},
++ {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
++ {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
++ }
++
++ private:
++ void doGet(crow::Response& res, const crow::Request& req,
++ const std::vector<std::string>& params) override
++ {
++ auto asyncResp = std::make_shared<AsyncResp>(res);
++
++ if (params.size() != 1)
++ {
++ messages::internalError(asyncResp->res);
++ return;
++ }
++
++ const std::string& id = params[0];
++
++ telemetry::getReport(asyncResp, id, schemaType,
++ getReportDefinitonProperties);
++ }
++
++ static std::vector<std::string>
++ toReportActions(const std::vector<std::string>& actions)
++ {
++ const boost::container::flat_map<std::string, std::string>
++ reportActions = {
++ {"Event", "RedfishEvent"},
++ {"Log", "LogToMetricReportsCollection"},
++ };
++
++ std::vector<std::string> out;
++ for (auto& action : actions)
++ {
++ auto found = reportActions.find(action);
++ if (found != reportActions.end())
++ {
++ out.emplace_back(found->second);
++ }
++ }
++ return out;
++ }
++
++ using ReadingParameters =
++ std::vector<std::tuple<std::vector<sdbusplus::message::object_path>,
++ std::string, std::string, std::string>>;
++ using Metrics = std::vector<std::map<
++ std::string, std::variant<std::string, std::vector<std::string>>>>;
++
++ static Metrics toMetrics(const ReadingParameters& params)
++ {
++ Metrics metrics;
++
++ for (auto& [sensorPaths, operationType, id, metadata] : params)
++ {
++ metrics.push_back({
++ {"MetricId", id},
++ {"MetricProperties", std::vector<std::string>() = {metadata}},
++ });
++ }
++
++ return metrics;
++ }
++
++ static void
++ getReportDefinitonProperties(const std::shared_ptr<AsyncResp> asyncResp,
++ const std::string& reportPath,
++ const std::string& id)
++ {
++ asyncResp->res.jsonValue["@odata.type"] = schemaType;
++ asyncResp->res.jsonValue["@odata.id"] =
++ telemetry::metricReportDefinitionUri + id;
++ asyncResp->res.jsonValue["Id"] = id;
++ asyncResp->res.jsonValue["Name"] = id;
++ asyncResp->res.jsonValue["MetricReport"]["@odata.id"] =
++ telemetry::metricReportUri + id;
++ asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
++
++ dbus::utility::getAllProperties(
++ [asyncResp](const boost::system::error_code ec,
++ const boost::container::flat_map<
++ std::string,
++ std::variant<std::string, std::vector<std::string>,
++ uint32_t, ReadingParameters>>& ret) {
++ if (ec)
++ {
++ messages::internalError(asyncResp->res);
++ BMCWEB_LOG_ERROR << "respHandler DBus error " << ec;
++ return;
++ }
++
++ json_util::assignIfPresent<std::vector<std::string>>(
++ ret, "ReportAction",
++ asyncResp->res.jsonValue["ReportActions"], toReportActions);
++ auto assigned = json_util::assignIfPresent<std::string>(
++ ret, "ReportingType",
++ asyncResp->res.jsonValue["MetricReportDefinitionType"]);
++ if (assigned &&
++ asyncResp->res.jsonValue["MetricReportDefinitionType"] ==
++ "Periodic")
++ {
++ json_util::assignIfPresent<uint32_t>(
++ ret, "ScanPeriod",
++ asyncResp->res
++ .jsonValue["Schedule"]["RecurrenceInterval"],
++ time_utils::toDurationFormat);
++ }
++ json_util::assignIfPresent<ReadingParameters>(
++ ret, "ReadingParameters",
++ asyncResp->res.jsonValue["Metrics"], toMetrics);
++ },
++ "xyz.openbmc_project.MonitoringService", reportPath,
++ "xyz.openbmc_project.MonitoringService.Report");
++ }
++
++ public:
++ static constexpr const char* schemaType =
++ "#MetricReportDefinition.v1_3_0.MetricReportDefinition";
++};
++} // namespace redfish
+diff --git a/redfish-core/lib/service_root.hpp b/redfish-core/lib/service_root.hpp
+index b6bd6e0..3302390 100644
+--- a/redfish-core/lib/service_root.hpp
++++ b/redfish-core/lib/service_root.hpp
+@@ -69,6 +69,8 @@ class ServiceRoot : public Node
+ res.jsonValue["Tasks"] = {{"@odata.id", "/redfish/v1/TaskService"}};
+ res.jsonValue["EventService"] = {
+ {"@odata.id", "/redfish/v1/EventService"}};
++ res.jsonValue["TelemetryService"] = {
++ {"@odata.id", "/redfish/v1/TelemetryService"}};
+ res.end();
+ }
+
+diff --git a/redfish-core/lib/telemetry_service.hpp b/redfish-core/lib/telemetry_service.hpp
+new file mode 100644
+index 0000000..a410700
+--- /dev/null
++++ b/redfish-core/lib/telemetry_service.hpp
+@@ -0,0 +1,92 @@
++/*
++// Copyright (c) 2018-2020 Intel Corporation
++//
++// Licensed under the Apache License, Version 2.0 (the "License");
++// you may not use this file except in compliance with the License.
++// You may obtain a copy of the License at
++//
++// http://www.apache.org/licenses/LICENSE-2.0
++//
++// Unless required by applicable law or agreed to in writing, software
++// distributed under the License is distributed on an "AS IS" BASIS,
++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
++// See the License for the specific language governing permissions and
++// limitations under the License.
++*/
++
++#pragma once
++
++#include "node.hpp"
++#include "utils/time_utils.hpp"
++
++#include <boost/container/flat_map.hpp>
++
++#include <variant>
++
++namespace redfish
++{
++
++class TelemetryService : public Node
++{
++ public:
++ TelemetryService(CrowApp& app) : Node(app, "/redfish/v1/TelemetryService/")
++ {
++ entityPrivileges = {
++ {boost::beast::http::verb::get, {{"Login"}}},
++ {boost::beast::http::verb::head, {{"Login"}}},
++ {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
++ {boost::beast::http::verb::put, {{"ConfigureManager"}}},
++ {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
++ {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
++ }
++
++ private:
++ void doGet(crow::Response& res, const crow::Request& req,
++ const std::vector<std::string>& params) override
++ {
++ res.jsonValue["@odata.type"] =
++ "#TelemetryService.v1_2_0.TelemetryService";
++ res.jsonValue["@odata.id"] = "/redfish/v1/TelemetryService";
++ res.jsonValue["Id"] = "TelemetryService";
++ res.jsonValue["Name"] = "Telemetry Service";
++
++ res.jsonValue["LogService"]["@odata.id"] =
++ "/redfish/v1/Managers/bmc/LogServices/Journal";
++ res.jsonValue["MetricReportDefinitions"]["@odata.id"] =
++ "/redfish/v1/TelemetryService/MetricReportDefinitions";
++ res.jsonValue["MetricReports"]["@odata.id"] =
++ "/redfish/v1/TelemetryService/MetricReports";
++
++ getMonitoringServiceProperties(res);
++ }
++
++ void getMonitoringServiceProperties(crow::Response& res)
++ {
++ auto asyncResp = std::make_shared<AsyncResp>(res);
++ dbus::utility::getAllProperties(
++ [asyncResp](
++ const boost::system::error_code ec,
++ const boost::container::flat_map<std::string,
++ std::variant<uint32_t>>& ret) {
++ if (ec)
++ {
++ asyncResp->res.jsonValue["Status"]["State"] = "Absent";
++ BMCWEB_LOG_ERROR << "respHandler DBus error " << ec;
++ return;
++ }
++
++ asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
++
++ json_util::assignIfPresent<uint32_t>(ret, "MaxReports",
++ asyncResp->res);
++ json_util::assignIfPresent<uint32_t>(
++ ret, "PollRateResolution",
++ asyncResp->res.jsonValue["MinCollectionInterval"],
++ time_utils::toDurationFormat);
++ },
++ "xyz.openbmc_project.MonitoringService",
++ "/xyz/openbmc_project/MonitoringService/Reports",
++ "xyz.openbmc_project.MonitoringService.ReportsManagement");
++ }
++};
++} // namespace redfish
+--
+2.16.6
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0002-Add-support-for-POST-in-MetricReportDefinitions.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0002-Add-support-for-POST-in-MetricReportDefinitions.patch
new file mode 100644
index 000000000..8a8690bf3
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0002-Add-support-for-POST-in-MetricReportDefinitions.patch
@@ -0,0 +1,594 @@
+From 941be2c7d819b4a55d5a8b67948e53658d907789 Mon Sep 17 00:00:00 2001
+From: "Wludzik, Jozef" <jozef.wludzik@intel.com>
+Date: Mon, 18 May 2020 11:56:57 +0200
+Subject: [PATCH 2/5] Add support for POST in MetricReportDefinitions
+
+Added POST action in MetricReportDefinitions node to allow user
+to add new MetricReportDefinition. Using minimal set of
+MetricReportDefinition parameters from user bmcweb converts it to
+DBus call "AddReport" to MonitoringService that serves as a backend
+for TelemetryService.
+
+Tested:
+ - Succesfully passed RedfishServiceValidator.py
+ - Validated good cases with different parameters for POST action
+ - Validated bad cases with different parameters for POST action
+ - Validated fromDurationFormat() with range of arguments starting
+ from PT0.0S up to P49D (it is an upper limit for uint32_t)
+
+Signed-off-by: Wludzik, Jozef <jozef.wludzik@intel.com>
+Signed-off-by: Krzysztof Grobelny <krzysztof.grobelny@intel.com>
+Change-Id: I2fed96848594451e22fde686f8c066d7770cc65a
+---
+ redfish-core/include/utils/time_utils.hpp | 49 +++
+ .../include/utils/validate_params_length.hpp | 109 +++++++
+ redfish-core/lib/metric_report_definition.hpp | 347 +++++++++++++++++++++
+ 3 files changed, 505 insertions(+)
+ create mode 100644 redfish-core/include/utils/validate_params_length.hpp
+
+diff --git a/redfish-core/include/utils/time_utils.hpp b/redfish-core/include/utils/time_utils.hpp
+index 0256b3f..c365585 100644
+--- a/redfish-core/include/utils/time_utils.hpp
++++ b/redfish-core/include/utils/time_utils.hpp
+@@ -57,6 +57,32 @@ std::string toDurationFormatItem(std::chrono::milliseconds& duration,
+ return ss.str();
+ }
+
++template <typename T>
++static long long fromDurationFormatItem(std::string_view& fmt,
++ const char* postfix)
++{
++ auto pos = fmt.find(postfix);
++ if (pos == std::string::npos)
++ {
++ return 0;
++ }
++
++ long out;
++ if constexpr (std::is_same<T, std::chrono::milliseconds>::value)
++ {
++ /* Half point is added to avoid numeric error on rounding */
++ out = static_cast<long>(std::strtof(fmt.data(), nullptr) *
++ std::chrono::milliseconds::period::den +
++ 0.5f);
++ }
++ else
++ {
++ out = std::strtol(fmt.data(), nullptr, 10);
++ }
++ fmt.remove_prefix(pos + 1);
++ return std::chrono::milliseconds(T(out)).count();
++}
++
+ } // namespace details
+
+ /**
+@@ -93,5 +119,28 @@ std::string toDurationFormat(const uint32_t ms)
+ return fmt;
+ }
+
++static uint32_t fromDurationFormat(std::string_view fmt)
++{
++ if (fmt.empty() || fmt[0] != 'P')
++ {
++ return 0;
++ }
++ using Days = std::chrono::duration<int, std::ratio<24 * 60 * 60>>;
++
++ fmt.remove_prefix(1);
++ auto out = details::fromDurationFormatItem<Days>(fmt, "D");
++ if (fmt[0] != 'T')
++ {
++ return static_cast<uint32_t>(out);
++ }
++
++ fmt.remove_prefix(1);
++ out += details::fromDurationFormatItem<std::chrono::hours>(fmt, "H");
++ out += details::fromDurationFormatItem<std::chrono::minutes>(fmt, "M");
++ out += details::fromDurationFormatItem<std::chrono::milliseconds>(fmt, "S");
++
++ return static_cast<uint32_t>(out);
++}
++
+ } // namespace time_utils
+ } // namespace redfish
+diff --git a/redfish-core/include/utils/validate_params_length.hpp b/redfish-core/include/utils/validate_params_length.hpp
+new file mode 100644
+index 0000000..c4e0569
+--- /dev/null
++++ b/redfish-core/include/utils/validate_params_length.hpp
+@@ -0,0 +1,109 @@
++#pragma once
++
++namespace redfish
++{
++namespace detail
++{
++template <class Limits, size_t... Seq>
++bool validateParamsLength(crow::Response& res, Limits&& limits,
++ std::index_sequence<Seq...>)
++{
++ return (... && std::get<Seq>(limits).validate(res));
++}
++} // namespace detail
++
++template <class T>
++struct ItemSizeValidator
++{
++ ItemSizeValidator(const T&& item, std::string_view name, size_t limit) :
++ item(std::forward<const T>(item)), name(name), limit(limit)
++ {}
++
++ bool validate(crow::Response& res) const
++ {
++ return ItemSizeValidator<T>::validateItem(res, item, name, limit);
++ }
++
++ private:
++ static bool validateItem(crow::Response& res, size_t item,
++ std::string_view name, size_t limit)
++ {
++ if (item > static_cast<size_t>(limit))
++ {
++ messages::stringValueTooLong(res, std::string(name),
++ static_cast<int>(limit));
++ return false;
++ }
++ return true;
++ }
++
++ static bool validateItem(crow::Response& res, std::string_view item,
++ std::string_view name, size_t limit)
++ {
++ return validateItem(res, item.size(), name, limit);
++ }
++
++ static bool validateItem(crow::Response& res, const std::string& item,
++ std::string_view name, size_t limit)
++ {
++ return validateItem(res, item.size(), name, limit);
++ }
++
++ static bool validateItem(crow::Response& res,
++ const sdbusplus::message::object_path& item,
++ std::string_view name, size_t limit)
++ {
++ return validateItem(res, item.str.size(), name, limit);
++ }
++
++ T item;
++ std::string_view name;
++ size_t limit;
++};
++
++template <class T>
++ItemSizeValidator(const T&, std::string_view, size_t)
++ -> ItemSizeValidator<const T&>;
++
++ItemSizeValidator(const char*, std::string_view, size_t)
++ ->ItemSizeValidator<std::string_view>;
++
++template <class ContainerT>
++struct ArrayItemsValidator
++{
++ ArrayItemsValidator(const ContainerT& item, std::string_view name,
++ size_t limit) :
++ item(item),
++ name(name), limit(limit)
++ {}
++
++ bool validate(crow::Response& res) const
++ {
++ return std::all_of(
++ item.begin(), item.end(), [&res, this](const auto& item) {
++ return ItemSizeValidator(item, name, limit).validate(res);
++ });
++ }
++
++ private:
++ const ContainerT& item;
++ std::string_view name;
++ size_t limit;
++};
++
++template <class T>
++bool validateParamLength(crow::Response& res, T&& item, std::string_view name,
++ size_t limit)
++{
++ return ItemSizeValidator(std::forward<T>(item), name, limit).validate(res);
++}
++
++template <class Limits>
++bool validateParamsLength(crow::Response& res, Limits&& limits)
++{
++ return detail::validateParamsLength(
++ res, std::forward<Limits>(limits),
++ std::make_index_sequence<std::tuple_size_v<std::decay_t<Limits>>>());
++}
++
++} // namespace redfish
+diff --git a/redfish-core/lib/metric_report_definition.hpp b/redfish-core/lib/metric_report_definition.hpp
+index d82ae59..ecbab0c 100644
+--- a/redfish-core/lib/metric_report_definition.hpp
++++ b/redfish-core/lib/metric_report_definition.hpp
+@@ -17,16 +17,29 @@
+ #pragma once
+
+ #include "node.hpp"
++#include "sensors.hpp"
+ #include "utils/telemetry_utils.hpp"
+ #include "utils/time_utils.hpp"
++#include "utils/validate_params_length.hpp"
+
++#include <boost/algorithm/string/join.hpp>
++#include <boost/algorithm/string/split.hpp>
+ #include <boost/container/flat_map.hpp>
+
++#include <regex>
+ #include <system_error>
++#include <tuple>
+ #include <variant>
+
+ namespace redfish
+ {
++static constexpr size_t maxShortParamLength = 255;
++static constexpr size_t maxLongParamLength = 1024;
++static constexpr size_t maxDbusNameLength = 255;
++static constexpr size_t maxArraySize = 100;
++static constexpr size_t maxReportIdLen =
++ maxDbusNameLength - std::string_view(telemetry::telemetryPath).size() -
++ std::string_view("/").size();
+
+ class MetricReportDefinitionCollection : public Node
+ {
+@@ -57,6 +70,339 @@ class MetricReportDefinitionCollection : public Node
+ telemetry::getReportCollection(asyncResp,
+ telemetry::metricReportDefinitionUri);
+ }
++
++ using ChassisSensorNode = std::pair<std::string, std::string>;
++ using DbusSensor = sdbusplus::message::object_path;
++ using DbusSensors = std::vector<DbusSensor>;
++ using MetricParam =
++ std::tuple<DbusSensors, std::string, std::string, std::string>;
++ using MetricParams = std::vector<MetricParam>;
++ /*
++ * AddReportArgs misses "Domain" parameter because it is constant for
++ * TelemetryService and equals "TelemetryService".
++ */
++ using AddReportArgs =
++ std::tuple<std::string, std::string, std::vector<std::string>, uint32_t,
++ MetricParams>;
++
++ void doPost(crow::Response& res, const crow::Request& req,
++ const std::vector<std::string>& params) override
++ {
++ auto asyncResp = std::make_shared<AsyncResp>(res);
++ AddReportArgs addReportArgs;
++ if (!getUserParameters(res, req, addReportArgs))
++ {
++ return;
++ }
++
++ boost::container::flat_set<ChassisSensorNode> chassisSensorSet;
++ auto unmatched = getChassisSensorNode(
++ std::get<MetricParams>(addReportArgs), chassisSensorSet);
++ if (unmatched)
++ {
++ messages::resourceNotFound(asyncResp->res, "MetricProperties",
++ *unmatched);
++ return;
++ }
++
++ auto addReportReq =
++ std::make_shared<AddReport>(addReportArgs, asyncResp);
++ for (auto& [chassis, sensorType] : chassisSensorSet)
++ {
++ retrieveUriToDbusMap(
++ chassis, sensorType,
++ [asyncResp, addReportReq](
++ const boost::beast::http::status status,
++ const boost::container::flat_map<std::string, std::string>&
++ uriToDbus) { *addReportReq += uriToDbus; });
++ }
++ }
++
++ static std::optional<std::string>
++ replaceReportActions(std::vector<std::string>& actions)
++ {
++ const boost::container::flat_map<std::string, std::string>
++ reportActions = {
++ {"RedfishEvent", "Event"},
++ {"LogToMetricReportsCollection", "Log"},
++ };
++
++ for (auto& action : actions)
++ {
++ auto found = reportActions.find(action);
++ if (found == reportActions.end())
++ {
++ return action;
++ }
++ action = found->second;
++ }
++ return std::nullopt;
++ }
++
++ static constexpr const std::array<const char*, 2> supportedDefinitionType =
++ {"Periodic", "OnRequest"};
++
++ static bool getUserParameters(crow::Response& res, const crow::Request& req,
++ AddReportArgs& params)
++ {
++ std::vector<nlohmann::json> metrics;
++ std::optional<nlohmann::json> schedule;
++ auto& [name, reportingType, reportActions, scanPeriod, metricParams] =
++ params;
++ if (!json_util::readJson(req, res, "Id", name, "Metrics", metrics,
++ "MetricReportDefinitionType", reportingType,
++ "ReportActions", reportActions, "Schedule",
++ schedule))
++ {
++ return false;
++ }
++
++ auto limits = std::make_tuple(
++ ItemSizeValidator(name, "Id", maxReportIdLen),
++ ItemSizeValidator(reportingType, "MetricReportDefinitionType",
++ maxShortParamLength),
++ ItemSizeValidator(reportActions.size(), "ReportActions.size()",
++ maxArraySize),
++ ArrayItemsValidator(reportActions, "ReportActions",
++ maxShortParamLength),
++ ItemSizeValidator(metrics.size(), "Metrics.size()", maxArraySize));
++
++ if (!validateParamsLength(res, std::move(limits)))
++ {
++ return false;
++ }
++
++ constexpr const char* allowedCharactersInName =
++ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
++ "_";
++ if (name.empty() || name.find_first_not_of(allowedCharactersInName) !=
++ std::string::npos)
++ {
++ BMCWEB_LOG_ERROR << "Failed to match " << name
++ << " with allowed character "
++ << allowedCharactersInName;
++ messages::propertyValueFormatError(res, name, "Id");
++ return false;
++ }
++
++ if (!std::any_of(
++ supportedDefinitionType.begin(), supportedDefinitionType.end(),
++ [reportingType](auto& x) { return reportingType == x; }))
++ {
++ messages::propertyValueNotInList(res, reportingType,
++ "MetricReportDefinitionType");
++ return false;
++ }
++
++ auto unmatched = replaceReportActions(reportActions);
++ if (unmatched)
++ {
++ messages::propertyValueNotInList(res, *unmatched, "ReportActions");
++ return false;
++ }
++
++ if (reportingType == "Periodic")
++ {
++ if (!schedule)
++ {
++ messages::createFailedMissingReqProperties(res, "Schedule");
++ return false;
++ }
++
++ std::string interval;
++ if (!json_util::readJson(*schedule, res, "RecurrenceInterval",
++ interval))
++ {
++ return false;
++ }
++
++ if (!validateParamLength(res, interval, "RecurrenceInterval",
++ maxShortParamLength))
++ {
++ return false;
++ }
++
++ constexpr const char* durationPattern =
++ "-?P(\\d+D)?(T(\\d+H)?(\\d+M)?(\\d+(.\\d+)?S)?)?";
++ if (!std::regex_match(interval, std::regex(durationPattern)))
++ {
++ messages::propertyValueFormatError(res, interval,
++ "RecurrenceInterval");
++ return false;
++ }
++
++ scanPeriod = time_utils::fromDurationFormat(interval);
++ }
++
++ return fillMetricParams(metrics, res, metricParams);
++ }
++
++ static bool fillMetricParams(std::vector<nlohmann::json>& metrics,
++ crow::Response& res,
++ MetricParams& metricParams)
++ {
++ metricParams.reserve(metrics.size());
++ for (auto& m : metrics)
++ {
++ std::string metricId;
++ std::vector<std::string> metricProperties;
++ if (!json_util::readJson(m, res, "MetricId", metricId,
++ "MetricProperties", metricProperties))
++ {
++ return false;
++ }
++
++ auto limits = std::make_tuple(
++ ItemSizeValidator(metricId, "MetricId", maxLongParamLength),
++ ItemSizeValidator(metricProperties.size(),
++ "MetricProperties.size()", maxArraySize),
++ ArrayItemsValidator(metricProperties, "MetricProperties",
++ maxLongParamLength));
++
++ if (!validateParamsLength(res, std::move(limits)))
++ {
++ return false;
++ }
++
++ DbusSensors dbusSensors;
++ dbusSensors.reserve(metricProperties.size());
++ std::for_each(
++ metricProperties.begin(), metricProperties.end(),
++ [&dbusSensors](auto& x) { dbusSensors.emplace_back(x); });
++
++ metricParams.emplace_back(
++ dbusSensors, "SINGLE", metricId,
++ boost::algorithm::join(metricProperties, ", "));
++ }
++ return true;
++ }
++
++ static std::optional<std::string> getChassisSensorNode(
++ const MetricParams& metricParams,
++ boost::container::flat_set<ChassisSensorNode>& matched)
++ {
++ for (const auto& metricParam : metricParams)
++ {
++ const auto& sensors = std::get<DbusSensors>(metricParam);
++ for (const auto& sensor : sensors)
++ {
++ /*
++ * Support only following paths:
++ * "/redfish/v1/Chassis/<chassis>/Power#/..."
++ * "/redfish/v1/Chassis/<chassis>/Sensors/..."
++ * "/redfish/v1/Chassis/<chassis>/Thermal#/..."
++ */
++ constexpr const char* uriPattern =
++ "\\/redfish\\/v1\\/Chassis\\/(\\w+)\\/"
++ "(Power|Sensors|Thermal)[#]?\\/.*";
++ std::smatch m;
++ if (!std::regex_match(sensor.str, m, std::regex(uriPattern)) ||
++ m.size() != 3)
++ {
++ BMCWEB_LOG_ERROR << "Failed to match " << sensor.str
++ << " with pattern " << uriPattern;
++ return sensor;
++ }
++
++ BMCWEB_LOG_DEBUG << "Chassis=" << m[1] << ", Type=" << m[2];
++ matched.emplace(m[1], m[2]);
++ }
++ }
++ return std::nullopt;
++ }
++
++ static std::optional<std::string> replaceUriWithDbus(
++ const boost::container::flat_map<std::string, std::string>& uriToDbus,
++ MetricParams& metricParams)
++ {
++ for (auto& metricParam : metricParams)
++ {
++ auto& dbusSensors = std::get<DbusSensors>(metricParam);
++ for (auto& uri : dbusSensors)
++ {
++ auto dbus = uriToDbus.find(uri);
++ if (dbus == uriToDbus.end())
++ {
++ BMCWEB_LOG_ERROR << "Failed to find DBus sensor "
++ "corresponding to URI "
++ << uri.str;
++ return uri;
++ }
++ uri = dbus->second;
++ }
++ }
++ return std::nullopt;
++ }
++
++ static void addReport(std::shared_ptr<AsyncResp> asyncResp,
++ AddReportArgs args)
++ {
++ constexpr const char* domain = "TelemetryService";
++ auto& [name, reportingType, reportActions, scanPeriod, metricParams] =
++ args;
++
++ crow::connections::systemBus->async_method_call(
++ [asyncResp, name](const boost::system::error_code ec,
++ const std::string ret) {
++ if (ec == boost::system::errc::file_exists)
++ {
++ messages::resourceAlreadyExists(
++ asyncResp->res, "MetricReportDefinition", "Id", name);
++ return;
++ }
++ if (ec == boost::system::errc::too_many_files_open)
++ {
++ messages::createLimitReachedForResource(asyncResp->res);
++ return;
++ }
++ if (ec)
++ {
++ messages::internalError(asyncResp->res);
++ BMCWEB_LOG_ERROR << "respHandler DBus error " << ec;
++ return;
++ }
++
++ messages::created(asyncResp->res);
++ },
++ "xyz.openbmc_project.MonitoringService",
++ "/xyz/openbmc_project/MonitoringService/Reports",
++ "xyz.openbmc_project.MonitoringService.ReportsManagement",
++ "AddReport", name, domain, reportingType, reportActions, scanPeriod,
++ metricParams);
++ }
++
++ class AddReport
++ {
++ public:
++ AddReport(AddReportArgs& args, std::shared_ptr<AsyncResp>& asyncResp) :
++ asyncResp{asyncResp}, addReportArgs{args}
++ {}
++ ~AddReport()
++ {
++ auto unmatched = replaceUriWithDbus(
++ uriToDbus, std::get<MetricParams>(addReportArgs));
++ if (unmatched)
++ {
++ messages::resourceNotFound(asyncResp->res, "MetricProperties",
++ *unmatched);
++ return;
++ }
++
++ addReport(asyncResp, addReportArgs);
++ }
++
++ AddReport& operator+=(
++ const boost::container::flat_map<std::string, std::string>& rhs)
++ {
++ this->uriToDbus.insert(rhs.begin(), rhs.end());
++ return *this;
++ }
++
++ private:
++ std::shared_ptr<AsyncResp> asyncResp;
++ AddReportArgs addReportArgs;
++ boost::container::flat_map<std::string, std::string> uriToDbus{};
++ };
+ };
+
+ class MetricReportDefinition : public Node
+@@ -148,6 +494,7 @@ class MetricReportDefinition : public Node
+ asyncResp->res.jsonValue["MetricReport"]["@odata.id"] =
+ telemetry::metricReportUri + id;
+ asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
++ asyncResp->res.jsonValue["ReportUpdates"] = "Overwrite";
+
+ dbus::utility::getAllProperties(
+ [asyncResp](const boost::system::error_code ec,
+--
+2.16.6
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0003-Add-support-for-DELETE-in-MetricReportDefinitions-st.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0003-Add-support-for-DELETE-in-MetricReportDefinitions-st.patch
new file mode 100644
index 000000000..4c49b0cd3
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0003-Add-support-for-DELETE-in-MetricReportDefinitions-st.patch
@@ -0,0 +1,68 @@
+From 8b2f4a6fe57bf2410cdb22f8c3c695e98d583040 Mon Sep 17 00:00:00 2001
+From: "Wludzik, Jozef" <jozef.wludzik@intel.com>
+Date: Mon, 18 May 2020 12:40:15 +0200
+Subject: [PATCH 3/5] Add support for DELETE in MetricReportDefinitions/<str>
+
+Added support for DELETE action in MetricReportDefinitions/<str>
+node. It allows user to remove MetricReportDefinition together
+with MetricReport connected to it.
+
+Tested:
+ - Succesfully passed RedfishServiceValidator.py
+ - Validated DELETE action by removing exisiting
+ MetricReportDefinitions from MonitoringService
+ - Validated DELETE action with negative cases when
+ MetricReportDefinition does not exist
+
+Signed-off-by: Wludzik, Jozef <jozef.wludzik@intel.com>
+Change-Id: Iffde9f7bbf2955376e9714ac8d833967bd25eaa3
+---
+ redfish-core/lib/metric_report_definition.hpp | 32 +++++++++++++++++++++++++++
+ 1 file changed, 32 insertions(+)
+
+diff --git a/redfish-core/lib/metric_report_definition.hpp b/redfish-core/lib/metric_report_definition.hpp
+index ecbab0c..8e04ac8 100644
+--- a/redfish-core/lib/metric_report_definition.hpp
++++ b/redfish-core/lib/metric_report_definition.hpp
+@@ -533,6 +533,38 @@ class MetricReportDefinition : public Node
+ "xyz.openbmc_project.MonitoringService.Report");
+ }
+
++ void doDelete(crow::Response& res, const crow::Request& req,
++ const std::vector<std::string>& params) override
++ {
++ auto asyncResp = std::make_shared<AsyncResp>(res);
++ if (params.size() != 1)
++ {
++ messages::internalError(asyncResp->res);
++ return;
++ }
++
++ const std::string& id = params[0];
++ telemetry::getReport(asyncResp, id, schemaType, deleteReport);
++ }
++
++ static void deleteReport(const std::shared_ptr<AsyncResp>& asyncResp,
++ const std::string& path, const std::string& id)
++ {
++ crow::connections::systemBus->async_method_call(
++ [asyncResp](const boost::system::error_code ec) {
++ if (ec)
++ {
++ BMCWEB_LOG_ERROR << "respHandler DBus error " << ec;
++ messages::internalError(asyncResp->res);
++ return;
++ }
++
++ asyncResp->res.result(boost::beast::http::status::no_content);
++ },
++ "xyz.openbmc_project.MonitoringService", path,
++ "xyz.openbmc_project.Object.Delete", "Delete");
++ }
++
+ public:
+ static constexpr const char* schemaType =
+ "#MetricReportDefinition.v1_3_0.MetricReportDefinition";
+--
+2.16.6
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0004-Add-support-for-OnRequest-in-MetricReportDefinition.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0004-Add-support-for-OnRequest-in-MetricReportDefinition.patch
new file mode 100644
index 000000000..e996ac585
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0004-Add-support-for-OnRequest-in-MetricReportDefinition.patch
@@ -0,0 +1,169 @@
+From 9fc7d722b3192df9940062185b40ebb0fabad518 Mon Sep 17 00:00:00 2001
+From: Krzysztof Grobelny <krzysztof.grobelny@intel.com>
+Date: Mon, 8 Jun 2020 15:16:10 +0200
+Subject: [PATCH 4/5] Add support for "OnRequest" in MetricReportDefinition
+
+Added support for "OnRequest" of ReportingType property in
+MetricReportDefinition node. Now user is able to create
+MetricReportDefinition that is updated on every GET request
+on MetricReport.
+
+Tested:
+ - Succesfully passed RedfishServiceValidator.py
+ - Manually tested via curl
+
+Signed-off-by: Krzysztof Grobelny <krzysztof.grobelny@intel.com>
+Change-Id: I1cdfe47e56fdc5ec9753558145d0bf3645160aaf
+---
+ include/dbus_utility.hpp | 30 +++++++++++++++
+ redfish-core/include/utils/telemetry_utils.hpp | 8 ++--
+ redfish-core/lib/metric_report.hpp | 53 +++++++++++++++++++++++++-
+ 3 files changed, 87 insertions(+), 4 deletions(-)
+
+diff --git a/include/dbus_utility.hpp b/include/dbus_utility.hpp
+index 3df88d8..029d8d8 100644
+--- a/include/dbus_utility.hpp
++++ b/include/dbus_utility.hpp
+@@ -17,6 +17,7 @@
+
+ #include <sdbusplus/message.hpp>
+
++#include <functional>
+ #include <regex>
+
+ namespace dbus
+@@ -130,5 +131,34 @@ inline void getAllProperties(Callback&& callback, const std::string& service,
+ interface);
+ }
+
++template <typename T>
++static void getProperty(
++ std::function<void(const boost::system::error_code&, const T&)> callback,
++ const std::string& service, const std::string& path,
++ const std::string& interface, const std::string& property)
++{
++ crow::connections::systemBus->async_method_call(
++ [callback](const boost::system::error_code ec,
++ const std::variant<T>& value) {
++ if (ec)
++ {
++ callback(ec, T{});
++ return;
++ }
++
++ if (auto v = std::get_if<T>(&value))
++ {
++ callback(ec, *v);
++ return;
++ }
++
++ callback(boost::system::errc::make_error_code(
++ boost::system::errc::io_error),
++ T{});
++ },
++ service, path, "org.freedesktop.DBus.Properties", "Get", interface,
++ property);
++}
++
+ } // namespace utility
+ } // namespace dbus
+diff --git a/redfish-core/include/utils/telemetry_utils.hpp b/redfish-core/include/utils/telemetry_utils.hpp
+index 05ed00f..6c4e810 100644
+--- a/redfish-core/include/utils/telemetry_utils.hpp
++++ b/redfish-core/include/utils/telemetry_utils.hpp
+@@ -26,6 +26,8 @@ static constexpr const char* metricReportDefinitionUri =
+ "/redfish/v1/TelemetryService/MetricReportDefinitions/";
+ static constexpr const char* metricReportUri =
+ "/redfish/v1/TelemetryService/MetricReports/";
++static constexpr const char* monitoringService =
++ "xyz.openbmc_project.MonitoringService";
+ static constexpr const char* reportInterface =
+ "xyz.openbmc_project.MonitoringService.Report";
+ static constexpr const char* telemetryPath =
+@@ -66,9 +68,9 @@ static void getReport(const std::shared_ptr<AsyncResp>& asyncResp,
+ const std::array<const char*, 1> interfaces = {reportInterface};
+
+ dbus::utility::getSubTreePaths(
+- [asyncResp, id, schemaType,
+- callback](const boost::system::error_code ec,
+- const std::vector<std::string>& reports) {
++ [asyncResp, id, schemaType, callback = std::move(callback)](
++ const boost::system::error_code ec,
++ const std::vector<std::string>& reports) {
+ if (ec == boost::system::errc::no_such_file_or_directory)
+ {
+ messages::resourceNotFound(asyncResp->res, schemaType, id);
+diff --git a/redfish-core/lib/metric_report.hpp b/redfish-core/lib/metric_report.hpp
+index a52d680..877e7f1 100644
+--- a/redfish-core/lib/metric_report.hpp
++++ b/redfish-core/lib/metric_report.hpp
+@@ -85,7 +85,7 @@ class MetricReport : public Node
+ }
+
+ const std::string& id = params[0];
+- telemetry::getReport(asyncResp, id, schemaType, getReportProperties);
++ telemetry::getReport(asyncResp, id, schemaType, updateReportIfRequired);
+ }
+
+ using Readings =
+@@ -143,6 +143,57 @@ class MetricReport : public Node
+ "xyz.openbmc_project.MonitoringService.Report");
+ }
+
++ template <typename Callback>
++ static void updateReport(Callback&& callback,
++ const std::shared_ptr<AsyncResp>& asyncResp,
++ const std::string& path)
++ {
++ crow::connections::systemBus->async_method_call(
++ [asyncResp, callback{std::move(callback)}](
++ const boost::system::error_code& ec) {
++ if (ec)
++ {
++ messages::internalError(asyncResp->res);
++ return;
++ }
++
++ callback();
++ },
++ telemetry::monitoringService, path, telemetry::reportInterface,
++ "Update");
++ }
++
++ static void
++ updateReportIfRequired(const std::shared_ptr<AsyncResp> asyncResp,
++ const std::string& reportPath,
++ const std::string& id)
++ {
++ dbus::utility::getProperty<std::string>(
++ [asyncResp, id, reportPath](const boost::system::error_code& ec,
++ const std::string& reportingType) {
++ if (ec)
++ {
++ messages::internalError(asyncResp->res);
++ return;
++ }
++
++ if (reportingType == "OnRequest")
++ {
++ updateReport(
++ [asyncResp, reportPath, id] {
++ getReportProperties(asyncResp, reportPath, id);
++ },
++ asyncResp, reportPath);
++ }
++ else
++ {
++ getReportProperties(asyncResp, reportPath, id);
++ }
++ },
++ telemetry::monitoringService, reportPath,
++ telemetry::reportInterface, "ReportingType");
++ }
++
+ static constexpr const char* schemaType =
+ "#MetricReport.v1_3_0.MetricReport";
+ };
+--
+2.16.6
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0005-Add-support-for-MetricDefinition-scheme.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0005-Add-support-for-MetricDefinition-scheme.patch
new file mode 100644
index 000000000..f7da8a556
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0005-Add-support-for-MetricDefinition-scheme.patch
@@ -0,0 +1,535 @@
+From b1da8901b5985d6a77b63ca9eb0570b46528f0bd Mon Sep 17 00:00:00 2001
+From: "Wludzik, Jozef" <jozef.wludzik@intel.com>
+Date: Mon, 8 Jun 2020 17:15:54 +0200
+Subject: [PATCH 5/5] Add support for MetricDefinition scheme
+
+Added MetricDefinition node to redfish core. Now user is able to
+get all possible metrics that are present in system and are
+supported by TelemetryService.
+
+Tested:
+ - Succesfully passed RedfishServiceValidator.py
+ - Validated a presence of MetricDefinition members
+
+Signed-off-by: Wludzik, Jozef <jozef.wludzik@intel.com>
+Signed-off-by: Krzysztof Grobelny <krzysztof.grobelny@intel.com>
+Change-Id: I3086e1302e1ba2e5442d1367939fd5507a0cbc00
+---
+ redfish-core/include/redfish.hpp | 3 +
+ redfish-core/include/utils/telemetry_utils.hpp | 2 +
+ redfish-core/lib/metric_definition.hpp | 300 +++++++++++++++++++++++++
+ redfish-core/lib/metric_report.hpp | 65 +++++-
+ redfish-core/lib/sensors.hpp | 43 +++-
+ redfish-core/lib/telemetry_service.hpp | 2 +
+ 6 files changed, 402 insertions(+), 13 deletions(-)
+ create mode 100644 redfish-core/lib/metric_definition.hpp
+
+diff --git a/redfish-core/include/redfish.hpp b/redfish-core/include/redfish.hpp
+index 3d4c117..2a12bf9 100644
+--- a/redfish-core/include/redfish.hpp
++++ b/redfish-core/include/redfish.hpp
+@@ -25,6 +25,7 @@
+ #include "../lib/log_services.hpp"
+ #include "../lib/managers.hpp"
+ #include "../lib/message_registries.hpp"
++#include "../lib/metric_definition.hpp"
+ #include "../lib/metric_report.hpp"
+ #include "../lib/metric_report_definition.hpp"
+ #include "../lib/network_protocol.hpp"
+@@ -206,6 +207,8 @@ class RedfishService
+ nodes.emplace_back(std::make_unique<HypervisorSystem>(app));
+
+ nodes.emplace_back(std::make_unique<TelemetryService>(app));
++ nodes.emplace_back(std::make_unique<MetricDefinitionCollection>(app));
++ nodes.emplace_back(std::make_unique<MetricDefinition>(app));
+ nodes.emplace_back(
+ std::make_unique<MetricReportDefinitionCollection>(app));
+ nodes.emplace_back(std::make_unique<MetricReportDefinition>(app));
+diff --git a/redfish-core/include/utils/telemetry_utils.hpp b/redfish-core/include/utils/telemetry_utils.hpp
+index 6c4e810..bb747c4 100644
+--- a/redfish-core/include/utils/telemetry_utils.hpp
++++ b/redfish-core/include/utils/telemetry_utils.hpp
+@@ -22,6 +22,8 @@ namespace redfish
+ namespace telemetry
+ {
+
++static constexpr const char* metricDefinitionUri =
++ "/redfish/v1/TelemetryService/MetricDefinitions/";
+ static constexpr const char* metricReportDefinitionUri =
+ "/redfish/v1/TelemetryService/MetricReportDefinitions/";
+ static constexpr const char* metricReportUri =
+diff --git a/redfish-core/lib/metric_definition.hpp b/redfish-core/lib/metric_definition.hpp
+new file mode 100644
+index 0000000..837a068
+--- /dev/null
++++ b/redfish-core/lib/metric_definition.hpp
+@@ -0,0 +1,300 @@
++/*
++// Copyright (c) 2018-2020 Intel Corporation
++//
++// Licensed under the Apache License, Version 2.0 (the "License");
++// you may not use this file except in compliance with the License.
++// You may obtain a copy of the License at
++//
++// http://www.apache.org/licenses/LICENSE-2.0
++//
++// Unless required by applicable law or agreed to in writing, software
++// distributed under the License is distributed on an "AS IS" BASIS,
++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
++// See the License for the specific language governing permissions and
++// limitations under the License.
++*/
++
++#pragma once
++
++#include "node.hpp"
++#include "sensors.hpp"
++#include "utils/telemetry_utils.hpp"
++
++namespace redfish
++{
++
++namespace chassis
++{
++template <typename F>
++static inline void getChassisNames(F&& callback)
++{
++ const std::array<const char*, 2> interfaces = {
++ "xyz.openbmc_project.Inventory.Item.Board",
++ "xyz.openbmc_project.Inventory.Item.Chassis"};
++
++ dbus::utility::getSubTreePaths(
++ [callback{std::move(callback)}](const boost::system::error_code ec,
++ std::vector<std::string>& chassisList) {
++ if (ec)
++ {
++ return;
++ }
++
++ std::vector<std::string> chassisNames;
++ chassisNames.reserve(chassisList.size());
++ for (auto& chassisPath : chassisList)
++ {
++ auto pos = chassisPath.rfind("/");
++ if (pos == std::string::npos)
++ {
++ continue;
++ }
++ chassisNames.push_back(chassisPath.substr(pos + 1));
++ }
++
++ callback(chassisNames);
++ },
++ "/xyz/openbmc_project/inventory", 0, interfaces);
++}
++} // namespace chassis
++
++class MetricDefinitionCollection : public Node
++{
++ public:
++ MetricDefinitionCollection(CrowApp& app) :
++ Node(app, "/redfish/v1/TelemetryService/MetricDefinitions")
++ {
++ entityPrivileges = {
++ {boost::beast::http::verb::get, {{"Login"}}},
++ {boost::beast::http::verb::head, {{"Login"}}},
++ {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
++ {boost::beast::http::verb::put, {{"ConfigureManager"}}},
++ {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
++ {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
++ }
++
++ private:
++ void doGet(crow::Response& res, const crow::Request& req,
++ const std::vector<std::string>& params) override
++ {
++ res.jsonValue["@odata.type"] = "#MetricDefinitionCollection."
++ "MetricDefinitionCollection";
++ res.jsonValue["@odata.id"] =
++ "/redfish/v1/TelemetryService/MetricDefinitions";
++ res.jsonValue["Name"] = "Metric Definition Collection";
++ res.jsonValue["Members"] = nlohmann::json::array();
++ res.jsonValue["Members@odata.count"] = sensors::dbus::types.size();
++
++ auto asyncResp = std::make_shared<AsyncResp>(res);
++ auto collectionReduce = std::make_shared<CollectionGather>(asyncResp);
++ chassis::getChassisNames(
++ [asyncResp,
++ collectionReduce](const std::vector<std::string>& chassisNames) {
++ for (auto& chassisName : chassisNames)
++ {
++ for (auto& [sensorNode, _] : sensors::dbus::types)
++ {
++ BMCWEB_LOG_INFO << "Chassis: " << chassisName
++ << " sensor: " << sensorNode;
++ retrieveUriToDbusMap(
++ chassisName, sensorNode.data(),
++ [asyncResp, collectionReduce](
++ const boost::beast::http::status status,
++ const boost::container::flat_map<
++ std::string, std::string>& uriToDbus) {
++ *collectionReduce += uriToDbus;
++ });
++ }
++ }
++ });
++ }
++
++ class CollectionGather
++ {
++ public:
++ CollectionGather(const std::shared_ptr<AsyncResp>& asyncResp) :
++ asyncResp{asyncResp}
++ {
++ dbusTypes.reserve(sensors::dbus::paths.size());
++ }
++
++ ~CollectionGather()
++ {
++ json_util::dbusPathsToMembersArray(
++ asyncResp->res,
++ std::vector<std::string>(dbusTypes.begin(), dbusTypes.end()),
++ telemetry::metricDefinitionUri);
++ }
++
++ CollectionGather& operator+=(
++ const boost::container::flat_map<std::string, std::string>& rhs)
++ {
++ for (auto& [_, dbusSensor] : rhs)
++ {
++ auto pos = dbusSensor.rfind("/");
++ if (pos == std::string::npos)
++ {
++ BMCWEB_LOG_ERROR << "Received invalid DBus Sensor Path = "
++ << dbusSensor;
++ continue;
++ }
++
++ this->dbusTypes.insert(dbusSensor.substr(0, pos));
++ }
++ return *this;
++ }
++
++ private:
++ const std::shared_ptr<AsyncResp> asyncResp;
++ boost::container::flat_set<std::string> dbusTypes;
++ };
++};
++
++class MetricDefinition : public Node
++{
++ public:
++ MetricDefinition(CrowApp& app) :
++ Node(app, std::string(telemetry::metricDefinitionUri) + "<str>/",
++ std::string())
++ {
++ entityPrivileges = {
++ {boost::beast::http::verb::get, {{"Login"}}},
++ {boost::beast::http::verb::head, {{"Login"}}},
++ {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
++ {boost::beast::http::verb::put, {{"ConfigureManager"}}},
++ {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
++ {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
++ }
++
++ private:
++ void doGet(crow::Response& res, const crow::Request& req,
++ const std::vector<std::string>& params) override
++ {
++ auto asyncResp = std::make_shared<AsyncResp>(res);
++ if (params.size() != 1)
++ {
++ messages::internalError(asyncResp->res);
++ return;
++ }
++
++ const std::string& id = params[0];
++
++ size_t sensorIndex = 0;
++ for (auto& name : sensors::dbus::names)
++ {
++ if (name == id)
++ {
++ break;
++ }
++ sensorIndex++;
++ }
++ if (sensorIndex >= sensors::dbus::max)
++ {
++ messages::resourceNotFound(asyncResp->res, schemaType, id);
++ return;
++ }
++
++ auto definitionGather =
++ std::make_shared<DefinitionGather>(asyncResp, id);
++ chassis::getChassisNames(
++ [asyncResp, definitionGather,
++ sensorIndex](const std::vector<std::string>& chassisNames) {
++ for (auto& chassisName : chassisNames)
++ {
++ for (auto& [sensorNode, dbusPaths] : sensors::dbus::types)
++ {
++ auto found =
++ std::find(dbusPaths.begin(), dbusPaths.end(),
++ sensors::dbus::paths[sensorIndex]);
++ if (found == dbusPaths.end())
++ {
++ continue;
++ }
++
++ retrieveUriToDbusMap(
++ chassisName, sensorNode.data(),
++ [asyncResp, definitionGather](
++ const boost::beast::http::status status,
++ const boost::container::flat_map<
++ std::string, std::string>& uriToDbus) {
++ *definitionGather += uriToDbus;
++ });
++ }
++ }
++ });
++ }
++
++ class DefinitionGather
++ {
++ public:
++ DefinitionGather(const std::shared_ptr<AsyncResp>& asyncResp,
++ const std::string& id) :
++ id(id),
++ asyncResp{asyncResp}
++ {}
++ ~DefinitionGather()
++ {
++ if (redfishSensors.empty())
++ {
++ messages::resourceNotFound(asyncResp->res, schemaType, id);
++ return;
++ }
++
++ asyncResp->res.jsonValue["MetricProperties"] =
++ nlohmann::json::array();
++ auto& members = asyncResp->res.jsonValue["MetricProperties"];
++ for (auto& redfishSensor : redfishSensors)
++ {
++ members.push_back(redfishSensor);
++ }
++
++ asyncResp->res.jsonValue["Id"] = id;
++ asyncResp->res.jsonValue["Name"] = id;
++ asyncResp->res.jsonValue["@odata.id"] =
++ telemetry::metricDefinitionUri + id;
++ asyncResp->res.jsonValue["@odata.type"] = schemaType;
++ asyncResp->res.jsonValue["MetricDataType"] = "Decimal";
++ asyncResp->res.jsonValue["MetricType"] = "Numeric";
++ asyncResp->res.jsonValue["Implementation"] = "PhysicalSensor";
++ asyncResp->res.jsonValue["IsLinear"] = true;
++ asyncResp->res.jsonValue["TimestampAccuracy"] = "PT0.1S";
++ auto unit = sensorUnits.find(id);
++ if (unit != sensorUnits.end())
++ {
++ asyncResp->res.jsonValue["Units"] = unit->second;
++ }
++ }
++
++ DefinitionGather& operator+=(
++ const boost::container::flat_map<std::string, std::string>& rhs)
++ {
++ for (auto& [redfishSensor, dbusSensor] : rhs)
++ {
++ if (dbusSensor.find(id) != std::string::npos)
++ {
++ this->redfishSensors.push_back(redfishSensor);
++ }
++ }
++ return *this;
++ }
++
++ const std::string id;
++
++ private:
++ const std::shared_ptr<AsyncResp> asyncResp;
++ std::vector<std::string> redfishSensors;
++ const boost::container::flat_map<std::string, std::string> sensorUnits =
++ {{sensors::dbus::names[sensors::dbus::voltage], "V"},
++ {sensors::dbus::names[sensors::dbus::power], "W"},
++ {sensors::dbus::names[sensors::dbus::current], "A"},
++ {sensors::dbus::names[sensors::dbus::fan_tach], "RPM"},
++ {sensors::dbus::names[sensors::dbus::temperature], "Cel"},
++ {sensors::dbus::names[sensors::dbus::utilization], "%"},
++ {sensors::dbus::names[sensors::dbus::fan_pwm], "Duty cycle"}};
++ };
++
++ static constexpr const char* schemaType =
++ "#MetricDefinition.v1_0_3.MetricDefinition";
++};
++
++} // namespace redfish
+diff --git a/redfish-core/lib/metric_report.hpp b/redfish-core/lib/metric_report.hpp
+index 877e7f1..be72b18 100644
+--- a/redfish-core/lib/metric_report.hpp
++++ b/redfish-core/lib/metric_report.hpp
+@@ -91,6 +91,9 @@ class MetricReport : public Node
+ using Readings =
+ std::vector<std::tuple<std::string, std::string, double, int32_t>>;
+ using MetricValues = std::vector<std::map<std::string, std::string>>;
++ using ReadingParameters =
++ std::vector<std::tuple<std::vector<sdbusplus::message::object_path>,
++ std::string, std::string, std::string>>;
+
+ static MetricValues toMetricValues(const Readings& readings)
+ {
+@@ -109,6 +112,49 @@ class MetricReport : public Node
+ return metricValues;
+ }
+
++ static void addMetricDefinition(nlohmann::json& metrics,
++ const ReadingParameters& params)
++ {
++ for (auto& metric : metrics)
++ {
++ if (!metric.contains("MetricId"))
++ {
++ continue;
++ }
++
++ auto& id = metric["MetricId"].get_ref<std::string&>();
++ auto param =
++ std::find_if(params.begin(), params.end(), [id](const auto& x) {
++ return id == std::get<2>(x);
++ });
++ if (param == params.end())
++ {
++ continue;
++ }
++
++ auto& dbusPaths =
++ std::get<std::vector<sdbusplus::message::object_path>>(*param);
++ if (dbusPaths.size() > 1)
++ {
++ continue;
++ }
++
++ auto dbusPath = dbusPaths.begin();
++ for (size_t i = 0; i < sensors::dbus::paths.size(); i++)
++ {
++ if (dbusPath->str.find(sensors::dbus::paths[i]) ==
++ std::string::npos)
++ {
++ continue;
++ }
++ metric["MetricDefinition"]["@odata.id"] =
++ telemetry::metricDefinitionUri +
++ std::string(sensors::dbus::names[i]);
++ break;
++ }
++ }
++ }
++
+ static void getReportProperties(const std::shared_ptr<AsyncResp> asyncResp,
+ const std::string& reportPath,
+ const std::string& id)
+@@ -124,7 +170,8 @@ class MetricReport : public Node
+ [asyncResp](
+ const boost::system::error_code ec,
+ const boost::container::flat_map<
+- std::string, std::variant<Readings, int32_t>>& ret) {
++ std::string,
++ std::variant<Readings, int32_t, ReadingParameters>>& ret) {
+ if (ec)
+ {
+ messages::internalError(asyncResp->res);
+@@ -138,6 +185,22 @@ class MetricReport : public Node
+ json_util::assignIfPresent<Readings>(
+ ret, "Readings", asyncResp->res.jsonValue["MetricValues"],
+ toMetricValues);
++
++ auto found = ret.find("ReadingParameters");
++ if (found != ret.end())
++ {
++ auto params =
++ std::get_if<ReadingParameters>(&found->second);
++ if (params)
++ {
++ auto& jsonValue = asyncResp->res.jsonValue;
++ if (jsonValue.contains("MetricValues"))
++ {
++ addMetricDefinition(jsonValue["MetricValues"],
++ *params);
++ }
++ }
++ }
+ },
+ "xyz.openbmc_project.MonitoringService", reportPath,
+ "xyz.openbmc_project.MonitoringService.Report");
+diff --git a/redfish-core/lib/sensors.hpp b/redfish-core/lib/sensors.hpp
+index f12bbe0..1fa1009 100644
+--- a/redfish-core/lib/sensors.hpp
++++ b/redfish-core/lib/sensors.hpp
+@@ -53,20 +53,39 @@ static constexpr std::string_view thermal = "Thermal";
+
+ namespace dbus
+ {
++
++enum Index
++{
++ voltage = 0,
++ power,
++ current,
++ fan_tach,
++ temperature,
++ fan_pwm,
++ utilization,
++ max
++};
++
++static constexpr std::array<const char*, max> names = {
++ "voltage", "power", "current", "fan_tach",
++ "temperature", "fan_pwm", "utilization"};
++
++static constexpr std::array<const char*, max> paths = {
++ "/xyz/openbmc_project/sensors/voltage",
++ "/xyz/openbmc_project/sensors/power",
++ "/xyz/openbmc_project/sensors/current",
++ "/xyz/openbmc_project/sensors/fan_tach",
++ "/xyz/openbmc_project/sensors/temperature",
++ "/xyz/openbmc_project/sensors/fan_pwm",
++ "/xyz/openbmc_project/sensors/utilization"};
++
+ static const boost::container::flat_map<std::string_view,
+ std::vector<const char*>>
+- types = {{node::power,
+- {"/xyz/openbmc_project/sensors/voltage",
+- "/xyz/openbmc_project/sensors/power"}},
+- {node::sensors,
+- {"/xyz/openbmc_project/sensors/power",
+- "/xyz/openbmc_project/sensors/current",
+- "/xyz/openbmc_project/sensors/utilization"}},
+- {node::thermal,
+- {"/xyz/openbmc_project/sensors/fan_tach",
+- "/xyz/openbmc_project/sensors/temperature",
+- "/xyz/openbmc_project/sensors/fan_pwm"}}};
+-}
++ types = {
++ {node::power, {paths[voltage], paths[power]}},
++ {node::sensors, {paths[power], paths[current], paths[utilization]}},
++ {node::thermal, {paths[fan_tach], paths[temperature], paths[fan_pwm]}}};
++} // namespace dbus
+ } // namespace sensors
+
+ /**
+diff --git a/redfish-core/lib/telemetry_service.hpp b/redfish-core/lib/telemetry_service.hpp
+index a410700..79e4154 100644
+--- a/redfish-core/lib/telemetry_service.hpp
++++ b/redfish-core/lib/telemetry_service.hpp
+@@ -52,6 +52,8 @@ class TelemetryService : public Node
+
+ res.jsonValue["LogService"]["@odata.id"] =
+ "/redfish/v1/Managers/bmc/LogServices/Journal";
++ res.jsonValue["MetricDefinitions"]["@odata.id"] =
++ "/redfish/v1/TelemetryService/MetricDefinitions";
+ res.jsonValue["MetricReportDefinitions"]["@odata.id"] =
+ "/redfish/v1/TelemetryService/MetricReportDefinitions";
+ res.jsonValue["MetricReports"]["@odata.id"] =
+--
+2.16.6
+
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/telemetry/0006-Fix-MetricReport-timestamp-for-EventService.patch
new file mode 100644
index 000000000..75d49b6d6
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0006-Fix-MetricReport-timestamp-for-EventService.patch
@@ -0,0 +1,78 @@
+From b71f087a173c36a16526156fa34581673e2b860c 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
+
+Changed MetricReport timestamp type from std::string to int32_t.
+
+Signed-off-by: Wludzik, Jozef <jozef.wludzik@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
+--- a/redfish-core/include/event_service_manager.hpp
++++ b/redfish-core/include/event_service_manager.hpp
+@@ -38,7 +38,7 @@ namespace redfish
+ {
+
+ using ReadingsObjType =
+- std::vector<std::tuple<std::string, std::string, double, std::string>>;
++ std::vector<std::tuple<std::string, std::string, double, int32_t>>;
+ using EventServiceConfig = std::tuple<bool, uint32_t, uint32_t>;
+
+ static constexpr const char* eventFormatType = "Event";
+@@ -532,10 +532,12 @@ class Subscription
+ metricValuesArray.push_back({});
+ nlohmann::json& entry = metricValuesArray.back();
+
+- entry = {{"MetricId", std::get<0>(it)},
+- {"MetricProperty", std::get<1>(it)},
+- {"MetricValue", std::to_string(std::get<2>(it))},
+- {"Timestamp", std::get<3>(it)}};
++ auto& [id, property, value, timestamp] = it;
++
++ entry = {{"MetricId", id},
++ {"MetricProperty", property},
++ {"MetricValue", value},
++ {"Timestamp", crow::utility::getDateTime(timestamp)}};
+ }
+
+ nlohmann::json msg = {
+@@ -1266,7 +1268,7 @@ class EventServiceManager
+ [idStr{std::move(idStr)}](
+ const boost::system::error_code ec,
+ boost::container::flat_map<
+- std::string, std::variant<std::string, ReadingsObjType>>&
++ std::string, std::variant<int32_t, ReadingsObjType>>&
+ resp) {
+ if (ec)
+ {
+@@ -1275,8 +1277,8 @@ class EventServiceManager
+ return;
+ }
+
+- const std::string* timestampPtr =
+- std::get_if<std::string>(&resp["Timestamp"]);
++ const int32_t* timestampPtr =
++ std::get_if<int32_t>(&resp["Timestamp"]);
+ if (!timestampPtr)
+ {
+ BMCWEB_LOG_DEBUG << "Failed to Get timestamp.";
+@@ -1303,8 +1305,9 @@ class EventServiceManager
+ std::shared_ptr<Subscription> entry = it.second;
+ if (entry->eventFormatType == metricReportFormatType)
+ {
+- entry->filterAndSendReports(idStr, *timestampPtr,
+- *readingsPtr);
++ entry->filterAndSendReports(
++ idStr, crow::utility::getDateTime(*timestampPtr),
++ *readingsPtr);
+ }
+ }
+ },
+--
+2.16.6
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/README b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/README
new file mode 100644
index 000000000..2929b0aec
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/README
@@ -0,0 +1,21 @@
+These patches are mirror of upstream TelemetryService implementation.
+Until change is integrated they will be manually merged here to enable feature in Intel builds.
+
+Current revisions:
+- Redfish TelemetryService schema implementation
+ https://gerrit.openbmc-project.xyz/c/openbmc/bmcweb/+/31692/29
+
+- Add support for POST in MetricReportDefinitions
+ https://gerrit.openbmc-project.xyz/c/openbmc/bmcweb/+/32536/24
+
+- Add support for DELETE in MetricReportDefinitions/<str>
+ https://gerrit.openbmc-project.xyz/c/openbmc/bmcweb/+/32537/23
+
+- Add support for "OnRequest" in MetricReportDefinition
+ https://gerrit.openbmc-project.xyz/c/openbmc/bmcweb/+/33358/17
+
+- Add support for MetricDefinition scheme
+ https://gerrit.openbmc-project.xyz/c/openbmc/bmcweb/+/33363/20
+
+- Temporary patch for EventService because of change in design
+ 0006-Fix-MetricReport-timestamp-for-EventService.patch
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 5c70f25d7..5a44eec78 100644
--- a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb_%.bbappend
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb_%.bbappend
@@ -1,6 +1,8 @@
# todo(james) remove nobranch
SRC_URI = "git://github.com/openbmc/bmcweb.git"
-SRCREV = "a502de3d661acf95613d4e4d27c9611f2c8148ea"
+SRCREV = "6964c9820ad101d6fc30badd1ae353efea3dd094"
+
+DEPENDS += "boost-url"
FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
@@ -13,14 +15,37 @@ GROUPADD_PARAM_${PN} = "web; redfish "
SRC_URI += "file://0001-Firmware-update-support-for-StandBySpare.patch \
file://0002-Use-chip-id-based-UUID-for-Service-Root.patch \
file://0003-bmcweb-changes-for-setting-ApplyOptions-ClearCfg.patch \
+ file://0004-Remove-QueryString.patch \
+ file://0004-bmcweb-handle-device-or-resource-busy-exception.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 \
+"
+
+# Temporary downstream mirror of upstream patches, see telemetry\README for details
+SRC_URI += "file://telemetry/0001-Redfish-TelemetryService-schema-implementation.patch \
+ file://telemetry/0002-Add-support-for-POST-in-MetricReportDefinitions.patch \
+ 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
+do_install_append() {
+ install -d ${D}/var/lib/bmcweb
+}
+
# Enable PFR support
EXTRA_OECMAKE += "${@bb.utils.contains('IMAGE_FSTYPES', 'intel-pfr', '-DBMCWEB_ENABLE_REDFISH_PROVISIONING_FEATURE=ON', '', d)}"
-# Enable NBD_PROXY
+# Enable NBD proxy embedded in bmcweb
EXTRA_OECMAKE += " -DBMCWEB_ENABLE_VM_NBDPROXY=ON"
+# Disable dependency on external nbd-proxy application
+EXTRA_OECMAKE += " -DBMCWEB_ENABLE_VM_WEBSOCKET=OFF"
+RDEPENDS_${PN}_remove += "jsnbd"
+
# Enable Validation unsecure based on IMAGE_FEATURES
EXTRA_OECMAKE += "${@bb.utils.contains('EXTRA_IMAGE_FEATURES', 'validation-unsecure', '-DBMCWEB_ENABLE_VALIDATION_UNSECURE_FEATURE=ON', '', d)}"
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/pmci/libmctp-intel_git.bb b/meta-openbmc-mods/meta-common/recipes-phosphor/pmci/libmctp-intel_git.bb
index 055e9710e..43f0785e5 100644
--- a/meta-openbmc-mods/meta-common/recipes-phosphor/pmci/libmctp-intel_git.bb
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/pmci/libmctp-intel_git.bb
@@ -2,7 +2,7 @@ SUMMARY = "libmctp_intel"
DESCRIPTION = "Implementation of MCTP(DMTF DSP0236)"
SRC_URI = "git://github.com/Intel-BMC/libmctp.git;protocol=ssh"
-SRCREV = "58581630af62fce296206e9d09da38cf1d6d1a0f"
+SRCREV = "467717ed557169e86be2c694e616fbfa9f5982c7"
S = "${WORKDIR}/git/"
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/pmci/mctp-emulator.bb b/meta-openbmc-mods/meta-common/recipes-phosphor/pmci/mctp-emulator.bb
index 829bc1636..98d2d11e4 100644
--- a/meta-openbmc-mods/meta-common/recipes-phosphor/pmci/mctp-emulator.bb
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/pmci/mctp-emulator.bb
@@ -5,7 +5,7 @@ LICENSE = "Apache-2.0"
LIC_FILES_CHKSUM = "file://LICENSE;md5=bcd9ada3a943f58551867d72893cc9ab"
SRC_URI = "git://github.com/Intel-BMC/pmci.git;protocol=ssh"
-SRCREV = "cd15b3175e2dd8315d1e01634f2c8a24174c9b21"
+SRCREV = "1bc2bddcff7104cc9040e9b2688761b2d9b32099"
S = "${WORKDIR}/git/mctp_emulator/"
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/pmci/mctpd.bb b/meta-openbmc-mods/meta-common/recipes-phosphor/pmci/mctpd.bb
index f20426ba1..740fd460e 100644
--- a/meta-openbmc-mods/meta-common/recipes-phosphor/pmci/mctpd.bb
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/pmci/mctpd.bb
@@ -5,7 +5,7 @@ LICENSE = "Apache-2.0"
LIC_FILES_CHKSUM = "file://LICENSE;md5=e3fc50a88d0a364313df4b21ef20c29e"
SRC_URI = "git://github.com/Intel-BMC/pmci.git;protocol=ssh"
-SRCREV = "cd15b3175e2dd8315d1e01634f2c8a24174c9b21"
+SRCREV = "1bc2bddcff7104cc9040e9b2688761b2d9b32099"
S = "${WORKDIR}/git/mctpd/"
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/sel-logger/phosphor-sel-logger_%.bbappend b/meta-openbmc-mods/meta-common/recipes-phosphor/sel-logger/phosphor-sel-logger_%.bbappend
index 67d8854d2..8ebca0b9e 100644
--- a/meta-openbmc-mods/meta-common/recipes-phosphor/sel-logger/phosphor-sel-logger_%.bbappend
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/sel-logger/phosphor-sel-logger_%.bbappend
@@ -1,4 +1,4 @@
# Enable downstream autobump
SRC_URI = "git://github.com/openbmc/phosphor-sel-logger.git"
-SRCREV = "761bf202ba9db9fe644f8f400a5e768abe1a70cf"
+SRCREV = "25b26e162bd109b51aa09b16f26f9aa3d9d940fa"
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 882547ea7..ac45a8114 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 = "5591cf0860895607bda0b8ae713e6b05ac0623b1"
+SRCREV = "623723b9e827f52a05cfe2dac8b4ef5d285fb6af"
#SRC_URI = "git://github.com/openbmc/dbus-sensors.git"
DEPENDS_append = " libgpiod libmctp"
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/service-config-manager/service-config-manager_%.bbappend b/meta-openbmc-mods/meta-common/recipes-phosphor/service-config-manager/service-config-manager_%.bbappend
index 6d26a95a9..c34d7af43 100644
--- a/meta-openbmc-mods/meta-common/recipes-phosphor/service-config-manager/service-config-manager_%.bbappend
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/service-config-manager/service-config-manager_%.bbappend
@@ -1,5 +1,6 @@
inherit meson pkgconfig systemd
-SRC_URI = "git://github.com/openbmc/service-config-manager"
-SRCREV = "1a885d98eea964bd9a3d57152dcaae7d4808211f"
+SRC_URI = "git://github.com/openbmc/service-config-manager;nobranch=1"
+# Move to latest version, only when sdbusplus is bumped up
+SRCREV = "0f2b1414d0dda4534008fc5eb0e939d99287c0eb"
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/settings/settings_git.bb b/meta-openbmc-mods/meta-common/recipes-phosphor/settings/settings_git.bb
index e15525bba..3fe7a1782 100644
--- a/meta-openbmc-mods/meta-common/recipes-phosphor/settings/settings_git.bb
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/settings/settings_git.bb
@@ -1,7 +1,7 @@
SUMMARY = "Settings"
SRC_URI = "git://github.com/Intel-BMC/settings.git;protocol=ssh"
-SRCREV = "cf55f85c9cd676736356f06fc47a7e98abd297f3"
+SRCREV = "5d2150656d23412c59acd4da7b9f155902f089d9"
PV = "0.1+git${SRCPV}"
LICENSE = "Apache-2.0"
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/special-mode-mgr/special-mode-mgr_git.bb b/meta-openbmc-mods/meta-common/recipes-phosphor/special-mode-mgr/special-mode-mgr_git.bb
index ea8971eb4..e27f2295c 100644
--- a/meta-openbmc-mods/meta-common/recipes-phosphor/special-mode-mgr/special-mode-mgr_git.bb
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/special-mode-mgr/special-mode-mgr_git.bb
@@ -9,7 +9,7 @@ LICENSE = "Apache-2.0"
LIC_FILES_CHKSUM = "file://LICENSE;md5=e3fc50a88d0a364313df4b21ef20c29e"
SRC_URI = "git://github.com/Intel-BMC/special-mode-manager.git;protocol=ssh"
-SRCREV = "658d313be17b971aedae69e9edbba5f26667dd03"
+SRCREV = "e9bcb94f78ec9dad22bc008e1abdb18f16f39a40"
EXTRA_OECMAKE += "${@bb.utils.contains('EXTRA_IMAGE_FEATURES', 'validation-unsecure', '-DBMC_VALIDATION_UNSECURE_FEATURE=ON', '', d)}"
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/virtual-media/virtual-media.bb b/meta-openbmc-mods/meta-common/recipes-phosphor/virtual-media/virtual-media.bb
index 333611dbb..2b0f167c4 100644
--- a/meta-openbmc-mods/meta-common/recipes-phosphor/virtual-media/virtual-media.bb
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/virtual-media/virtual-media.bb
@@ -14,8 +14,7 @@ SYSTEMD_SERVICE_${PN} += "xyz.openbmc_project.VirtualMedia.service"
DEPENDS = "udev boost nlohmann-json systemd sdbusplus"
-# Needed for legacy mode
-RDEPENDS_${PN} = "nbdkit"
+RDEPENDS_${PN} = "nbd-client nbdkit"
inherit cmake systemd
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/webui/phosphor-webui_%.bbappend b/meta-openbmc-mods/meta-common/recipes-phosphor/webui/phosphor-webui_%.bbappend
index ce46ec5cd..4a188f28e 100644
--- a/meta-openbmc-mods/meta-common/recipes-phosphor/webui/phosphor-webui_%.bbappend
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/webui/phosphor-webui_%.bbappend
@@ -1,4 +1,4 @@
SRC_URI = "git://github.com/Intel-BMC/phosphor-webui;protocol=ssh;branch=intel2"
FILESEXTRAPATHS_prepend_intel := "${THISDIR}/${PN}:"
-SRCREV = "7d6650577d28a52e7be47dd2106d9e0f3b6e1c59"
+SRCREV = "3348cfbfd54e52a795516bc4a906e128c1bc6bcf"
diff --git a/meta-openbmc-mods/meta-common/recipes-support/boost-url/boost-url_git.bb b/meta-openbmc-mods/meta-common/recipes-support/boost-url/boost-url_git.bb
new file mode 100644
index 000000000..6d4635b66
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-support/boost-url/boost-url_git.bb
@@ -0,0 +1,17 @@
+DESCRIPTION = "Boost.URL is a library for manipulating Uniform Resource Identifiers (URI) and Locators (URL)"
+HOMEPAGE = "https://github.com/CPPAlliance/url"
+SECTION = "libs"
+LICENSE = "BSL-1.0"
+LIC_FILES_CHKSUM = "file://LICENSE_1_0.txt;md5=e4224ccaecb14d942c71d31bef20d78c"
+
+SRC_URI = "git://github.com/CPPAlliance/url.git"
+
+SRCREV = "a56ae0df6d3078319755fbaa67822b4fa7fd352b"
+
+S = "${WORKDIR}/git"
+
+inherit cmake
+
+DEPENDS = "boost"
+
+BBCLASSEXTEND = "native nativesdk"
diff --git a/meta-openbmc-mods/meta-common/recipes-x86/chassis/x86-power-control_%.bbappend b/meta-openbmc-mods/meta-common/recipes-x86/chassis/x86-power-control_%.bbappend
index b107c8873..d2d918404 100755
--- a/meta-openbmc-mods/meta-common/recipes-x86/chassis/x86-power-control_%.bbappend
+++ b/meta-openbmc-mods/meta-common/recipes-x86/chassis/x86-power-control_%.bbappend
@@ -1,3 +1,7 @@
+# Enable downstream autobump
+SRC_URI = "git://github.com/openbmc/x86-power-control.git;protocol=ssh"
+SRCREV = "273d789718ce2a7aaf49424f9cefcd89226da2a7"
+
FILESEXTRAPATHS_append := "${THISDIR}/${PN}:"
SRC_URI += " \
diff --git a/meta-openbmc-mods/meta-wht/recipes-core/host-error-monitor/host-error-monitor/0001-Filter-memory-thermtrip-events-based-on-DIMM-status.patch b/meta-openbmc-mods/meta-wht/recipes-core/host-error-monitor/host-error-monitor/0001-Filter-memory-thermtrip-events-based-on-DIMM-status.patch
new file mode 100644
index 000000000..30859d1a4
--- /dev/null
+++ b/meta-openbmc-mods/meta-wht/recipes-core/host-error-monitor/host-error-monitor/0001-Filter-memory-thermtrip-events-based-on-DIMM-status.patch
@@ -0,0 +1,153 @@
+From 0253fd1d68d6a42c95c425b1a61fa2d53b2b2469 Mon Sep 17 00:00:00 2001
+From: "Jason M. Bills" <jason.m.bills@intel.com>
+Date: Wed, 22 Jul 2020 14:30:04 -0700
+Subject: [PATCH] Filter memory thermtrip events based on DIMM status
+
+There is a race-condition on shutdown that makes it difficult to
+differentiate between a normal shutdown and a memory thermtrip
+shutdown. This race-condition will be resolved in the CPLD for
+future platforms but for now it requires a workaround.
+
+This workaround assumes that a memory thermtrip can only occur
+if a DIMM temperature sensor has already reached a critical
+threshold. When memory thermtrip asserts on shutdown, it only
+logs an error if a DIMM is critical; otherwise it is treated
+as a normal shutdown.
+
+Tested:
+Memory thermtrip errors no longer log on each power-off.
+Manually set a DIMM temperature above critical and verified
+that the memory thermtrip event is logged.
+
+Change-Id: I9c38b41db30046499297ee24cc3a2790920b19d3
+Signed-off-by: Jason M. Bills <jason.m.bills@intel.com>
+---
+ src/host_error_monitor.cpp | 77 +++++++++++++++++++++++++++++++++++++-
+ 1 file changed, 75 insertions(+), 2 deletions(-)
+
+diff --git a/src/host_error_monitor.cpp b/src/host_error_monitor.cpp
+index 1c6a2e70d..aa4a9b672 100644
+--- a/src/host_error_monitor.cpp
++++ b/src/host_error_monitor.cpp
+@@ -17,6 +17,7 @@
+ #include <systemd/sd-journal.h>
+
+ #include <boost/asio/posix/stream_descriptor.hpp>
++#include <boost/container/flat_set.hpp>
+ #include <gpiod.hpp>
+ #include <sdbusplus/asio/object_server.hpp>
+
+@@ -36,6 +37,9 @@ static std::shared_ptr<sdbusplus::asio::dbus_interface> associationCATAssert;
+
+ static const constexpr char* rootPath = "/xyz/openbmc_project/CallbackManager";
+
++static boost::container::flat_set<std::string> cpu1CriticalDIMMs;
++static boost::container::flat_set<std::string> cpu2CriticalDIMMs;
++
+ static bool hostOff = true;
+
+ static size_t caterrTimeoutMs = 2000;
+@@ -258,6 +262,67 @@ static void initializeHostState()
+ "xyz.openbmc_project.State.Host", "CurrentHostState");
+ }
+
++static std::shared_ptr<sdbusplus::bus::match::match>
++ startDIMMThresholdEventMonitor()
++{
++ return std::make_shared<sdbusplus::bus::match::match>(
++ *conn,
++ "type='signal',interface='org.freedesktop.DBus.Properties',member='"
++ "PropertiesChanged',arg0namespace='xyz.openbmc_project.Sensor."
++ "Threshold.Critical'",
++ [](sdbusplus::message::message& msg) {
++ std::string interfaceName;
++ boost::container::flat_map<std::string, std::variant<bool>>
++ propertiesChanged;
++ try
++ {
++ msg.read(interfaceName, propertiesChanged);
++ }
++ catch (std::exception& e)
++ {
++ std::cerr << "Unable to read threshold event\n";
++ return;
++ }
++ // We only want to check for CriticalAlarmHigh
++ if (propertiesChanged.begin()->first != "CriticalAlarmHigh")
++ {
++ return;
++ }
++ const bool* alarm =
++ std::get_if<bool>(&(propertiesChanged.begin()->second));
++ if (alarm == nullptr)
++ {
++ std::cerr << propertiesChanged.begin()->first
++ << " property invalid\n";
++ return;
++ }
++
++ // Get the sensor path and check if it's a DIMM sensor
++ std::string sensor = msg.get_path();
++ if (sensor.find("DIMM") == std::string::npos)
++ {
++ // Not a DIMM sensor
++ return;
++ }
++
++ // Determine which CPU the DIMM belongs to
++ boost::container::flat_set<std::string>& criticalDIMMs =
++ (sensor.find("CPU1") != std::string::npos) ? cpu1CriticalDIMMs
++ : cpu2CriticalDIMMs;
++
++ if (*alarm)
++ {
++ // DIMM crossed a critical threshold, so store it
++ criticalDIMMs.insert(sensor);
++ }
++ else
++ {
++ // DIMM is no longer critical, so remove it
++ criticalDIMMs.erase(sensor);
++ }
++ });
++}
++
+ static std::shared_ptr<sdbusplus::bus::match::match> startHostStateMonitor()
+ {
+ return std::make_shared<sdbusplus::bus::match::match>(
+@@ -826,7 +891,9 @@ static void cpu1MemtripHandler()
+
+ bool cpu1Memtrip =
+ gpioLineEvent.event_type == gpiod::line_event::FALLING_EDGE;
+- if (cpu1Memtrip)
++
++ // Only log a memory thermtrip if a DIMM is critical
++ if (cpu1Memtrip && !cpu1CriticalDIMMs.empty())
+ {
+ memThermTripLog(1);
+ }
+@@ -886,7 +953,9 @@ static void cpu2MemtripHandler()
+
+ bool cpu2Memtrip =
+ gpioLineEvent.event_type == gpiod::line_event::FALLING_EDGE;
+- if (cpu2Memtrip)
++
++ // Only log a memory thermtrip if a DIMM is critical
++ if (cpu2Memtrip && !cpu2CriticalDIMMs.empty())
+ {
+ memThermTripLog(2);
+ }
+@@ -1605,6 +1674,10 @@ int main(int argc, char* argv[])
+ std::shared_ptr<sdbusplus::bus::match::match> hostStateMonitor =
+ host_error_monitor::startHostStateMonitor();
+
++ // Start tracking critical DIMM status
++ std::shared_ptr<sdbusplus::bus::match::match> dimmThresholdEventMonitor =
++ host_error_monitor::startDIMMThresholdEventMonitor();
++
+ // Request CPU1_MISMATCH GPIO events
+ if (!host_error_monitor::requestGPIOInput(
+ "CPU1_MISMATCH", host_error_monitor::cpu1MismatchLine))
+--
+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
new file mode 100644
index 000000000..4b79757c0
--- /dev/null
+++ b/meta-openbmc-mods/meta-wht/recipes-core/host-error-monitor/host-error-monitor_%.bbappend
@@ -0,0 +1,5 @@
+FILESEXTRAPATHS_append := "${THISDIR}/${PN}:"
+
+SRC_URI += " \
+ file://0001-Filter-memory-thermtrip-events-based-on-DIMM-status.patch \
+ "