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