From 87a65e63bac789bca0607e0b4ab09d62517b95e7 Mon Sep 17 00:00:00 2001 From: Ed Tanous Date: Wed, 29 May 2019 10:29:58 -0700 Subject: Update to internal Signed-off-by: Ed Tanous --- .../ipmi/phosphor-ipmi-config/channel_config.json | 34 +- .../master_write_read_white_list.json | 45 ++- ...Modify-dbus-interface-for-chassis-control.patch | 33 -- .../0012-ipmi-set-get-boot-options.patch | 10 +- .../0014-Enable-get-device-guid-ipmi-command.patch | 45 --- ...ment-IPMI-Commmand-Get-Host-Restart-Cause.patch | 34 +- ...-Implement-IPMI-Master-Write-Read-command.patch | 351 --------------------- ...nt-set-front-panel-button-enables-command.patch | 27 +- .../0057-Add-timer-use-actions-support.patch | 10 +- ...ve-Get-SOL-config-parameter-to-host-ipmid.patch | 144 +++++++-- .../ipmi/phosphor-ipmi-host_%.bbappend | 22 +- .../ipmi/phosphor-ipmi-ipmb_%.bbappend | 2 +- .../org.openbmc.HostIpmi.SMM.service | 13 - .../phosphor-ipmi-kcs/org.openbmc.HostIpmi.service | 13 - .../ipmi/phosphor-ipmi-kcs_%.bbappend | 9 +- ...Session-Info-cmd-based-on-Upstream-review.patch | 50 +-- ...move-Get-SOL-Config-Command-from-Netipmid.patch | 336 ++++++++++++++++++++ .../ipmi/phosphor-ipmi-net_%.bbappend | 11 +- .../ipmi/phosphor-node-manager-proxy_git.bb | 2 +- 19 files changed, 587 insertions(+), 604 deletions(-) delete mode 100644 meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0003-Modify-dbus-interface-for-chassis-control.patch delete mode 100644 meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0014-Enable-get-device-guid-ipmi-command.patch delete mode 100644 meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0048-Implement-IPMI-Master-Write-Read-command.patch delete mode 100644 meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-kcs/org.openbmc.HostIpmi.SMM.service delete mode 100644 meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-kcs/org.openbmc.HostIpmi.service create mode 100644 meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-net/0011-Remove-Get-SOL-Config-Command-from-Netipmid.patch (limited to 'meta-openbmc-mods/meta-common/recipes-phosphor/ipmi') 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 index 13b945fd0..a7815a9a9 100644 --- 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 @@ -55,12 +55,12 @@ } }, "5" : { - "name" : "ICMB", + "name" : "RESERVED", "is_valid" : false, "active_sessions" : 0, "channel_info" : { - "medium_type" : "ipmb", - "protocol_type" : "ipmb-1.0", + "medium_type" : "reserved", + "protocol_type" : "na", "session_supported" : "session-less", "is_ipmi" : true } @@ -77,12 +77,12 @@ } }, "7" : { - "name" : "SMM", + "name" : "ipmi-kcs4", "is_valid" : true, "active_sessions" : 0, "channel_info" : { - "medium_type" : "ipmb", - "protocol_type" : "ipmb-1.0", + "medium_type" : "system-interface", + "protocol_type" : "kcs", "session_supported" : "session-less", "is_ipmi" : true } @@ -92,8 +92,8 @@ "is_valid" : true, "active_sessions" : 0, "channel_info" : { - "medium_type" : "ipmb", - "protocol_type" : "ipmb-1.0", + "medium_type" : "oem", + "protocol_type" : "oem", "session_supported" : "session-less", "is_ipmi" : true } @@ -125,8 +125,8 @@ "is_valid" : false, "active_sessions" : 0, "channel_info" : { - "medium_type" : "ipmb", - "protocol_type" : "ipmb-1.0", + "medium_type" : "reserved", + "protocol_type" : "na", "session_supported" : "session-less", "is_ipmi" : true } @@ -147,8 +147,8 @@ "is_valid" : false, "active_sessions" : 0, "channel_info" : { - "medium_type" : "ipmb", - "protocol_type" : "ipmb-1.0", + "medium_type" : "reserved", + "protocol_type" : "na", "session_supported" : "session-less", "is_ipmi" : true } @@ -158,19 +158,19 @@ "is_valid" : false, "active_sessions" : 0, "channel_info" : { - "medium_type" : "ipmb", - "protocol_type" : "ipmb-1.0", + "medium_type" : "unknown", + "protocol_type" : "na", "session_supported" : "session-less", "is_ipmi" : true } }, "15" : { - "name" : "SMS", + "name" : "ipmi-kcs3", "is_valid" : true, "active_sessions" : 0, "channel_info" : { - "medium_type" : "ipmb", - "protocol_type" : "ipmb-1.0", + "medium_type" : "system-interface", + "protocol_type" : "kcs", "session_supported" : "session-less", "is_ipmi" : true } diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-config/master_write_read_white_list.json b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-config/master_write_read_white_list.json index 9fdb3c916..6fc46f452 100644 --- 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 @@ -1,49 +1,76 @@ { "filters": [ { + "Description": "Allow full read - ignore first byte write value", "busId": "0x01", "slaveAddr": "0x4d", - "command": "0x00" + "slaveAddrMask": "0x00", + "command": "0x00", + "commandMask": "0xFF" }, { + "Description": "Allow full read - ignore first byte write value", "busId": "0x01", "slaveAddr": "0x57", - "command": "0x00" + "slaveAddrMask": "0x00", + "command": "0x00", + "commandMask": "0xFF" }, { + "Description": "Allow full read - ignore first byte write value", "busId": "0x02", "slaveAddr": "0x40", - "command": "0x00" + "slaveAddrMask": "0x00", + "command": "0x00", + "commandMask": "0xFF" }, { + "Description": "Allow full read - ignore first byte write value", "busId": "0x02", "slaveAddr": "0x49", - "command": "0x00" + "slaveAddrMask": "0x00", + "command": "0x00", + "commandMask": "0xFF" }, { + "Description": "Allow full read - ignore first byte write value", "busId": "0x02", "slaveAddr": "0x51", - "command": "0x00" + "slaveAddrMask": "0x00", + "command": "0x00", + "commandMask": "0xFF" }, { + "Description": "Allow full read - ignore first byte write value", "busId": "0x03", "slaveAddr": "0x44", - "command": "0x00" + "slaveAddrMask": "0x00", + "command": "0x00", + "commandMask": "0xFF" }, { + "Description": "Allow full read - ignore first byte write value", "busId": "0x03", "slaveAddr": "0x68", - "command": "0x00" + "slaveAddrMask": "0x00", + "command": "0x00", + "commandMask": "0xFF" }, { + "Description": "Allow full read - ignore first byte write value", "busId": "0x06", "slaveAddr": "0x40", - "command": "0x00" + "slaveAddrMask": "0x00", + "command": "0x00", + "commandMask": "0xFF" }, { + "Description": "Allow full read - ignore first byte write value", "busId": "0x07", "slaveAddr": "0x51", - "command": "0x00" + "slaveAddrMask": "0x00", + "command": "0x00", + "commandMask": "0xFF" } ] } 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 deleted file mode 100644 index 9061481ac..000000000 --- a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0003-Modify-dbus-interface-for-chassis-control.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 48ac37551cd51415deafe8b1dcb23ebeef1e8ade Mon Sep 17 00:00:00 2001 -From: Yong Li -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 -Signed-off-by: Yong Li ---- - 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/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 index 243015c95..fb5dcee09 100644 --- 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 @@ -21,9 +21,8 @@ index 666addb..77af2dc 100644 std::map sourceIpmiToDbus = { {0x01, Source::Sources::Network}, {0x02, Source::Sources::Disk}, -- {0x05, Source::Sources::ExternalMedia}, -+ {0x05, Source::Sources::DVD}, -+ {0x0f, Source::Sources::Removable}, + {0x05, Source::Sources::ExternalMedia}, ++ {0x0f, Source::Sources::RemovableMedia}, {ipmiDefault, Source::Sources::Default}}; std::map modeIpmiToDbus = { @@ -31,9 +30,8 @@ index 666addb..77af2dc 100644 std::map sourceDbusToIpmi = { {Source::Sources::Network, 0x01}, {Source::Sources::Disk, 0x02}, -- {Source::Sources::ExternalMedia, 0x05}, -+ {Source::Sources::DVD, 0x05}, -+ {Source::Sources::Removable, 0x0f}, + {Source::Sources::ExternalMedia, 0x05}, ++ {Source::Sources::RemovableMedia, 0x0f}, {Source::Sources::Default, ipmiDefault}}; std::map modeDbusToIpmi = { 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 deleted file mode 100644 index 46dd99466..000000000 --- a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0014-Enable-get-device-guid-ipmi-command.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 482a6cc52d0ec514d6da5f4bcb04b4991f3cc36e Mon Sep 17 00:00:00 2001 -From: Yong Li -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 ---- - 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("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/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 index af526c177..cba0cde32 100644 --- 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 @@ -1,4 +1,4 @@ -From c14e31ebc35e0bb7b843d84683f9f2698c9c08d7 Mon Sep 17 00:00:00 2001 +From 6d5a372e0cf98de4d97a88d2cd42a00b7a8f034f Mon Sep 17 00:00:00 2001 From: Yong Li Date: Sun, 16 Sep 2018 21:32:38 +0800 Subject: [PATCH] Implement IPMI Commmand - Get Host Restart Cause. @@ -25,16 +25,16 @@ Change-Id: Id3b32e271b85b5fc4c69d5ca40227f8f9c08ce48 Signed-off-by: Kuiying Wang Signed-off-by: Yong Li --- - chassishandler.cpp | 54 +++++++++++++++++++++++++++++++++++++++++++++++ - chassishandler.hpp | 1 + + 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 +index d20b220..8a8cb26 100644 --- a/chassishandler.cpp +++ b/chassishandler.cpp -@@ -107,6 +107,11 @@ static constexpr auto chassisPOHStateIntf = +@@ -90,6 +90,11 @@ static constexpr auto chassisPOHStateIntf = "xyz.openbmc_project.State.PowerOnHours"; static constexpr auto pOHCounterProperty = "POHCounter"; static constexpr auto match = "chassis0"; @@ -46,7 +46,7 @@ index 77af2dc..2a29755 100644 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 +@@ -176,6 +181,13 @@ struct set_sys_boot_options_t uint8_t data[SIZE_BOOT_OPTION]; } __attribute__((packed)); @@ -60,7 +60,7 @@ index 77af2dc..2a29755 100644 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, +@@ -1584,6 +1596,44 @@ ipmi_ret_t ipmi_chassis_set_sys_boot_options(ipmi_netfn_t netfn, ipmi_cmd_t cmd, return rc; } @@ -102,20 +102,20 @@ index 77af2dc..2a29755 100644 + 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) + /** @brief implements Get POH counter command + * @parameter + * - none @@ -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); + ipmi::chassis::cmdSetPowerRestorePolicy, + ipmi::Privilege::Operator, + ipmiChassisSetPowerRestorePolicy); + + // + 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 +index 49b5ef8..2c42b11 100644 --- a/chassishandler.hpp +++ b/chassishandler.hpp @@ -17,6 +17,7 @@ enum ipmi_netfn_chassis_cmds @@ -127,10 +127,10 @@ index 0c6d5a2..e37c4f1 100644 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 +index c1fca1d..94232de 100644 --- a/host-ipmid-whitelist.conf +++ b/host-ipmid-whitelist.conf -@@ -3,6 +3,7 @@ +@@ -4,6 +4,7 @@ 0x00:0x02 //: 0x00:0x05 //: 0x00:0x06 //: @@ -139,5 +139,5 @@ index db54a49..827e2dc 100644 0x00:0x09 //: 0x00:0x0F //: -- -2.7.4 +2.17.1 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 deleted file mode 100644 index 542c4f667..000000000 --- a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0048-Implement-IPMI-Master-Write-Read-command.patch +++ /dev/null @@ -1,351 +0,0 @@ -From a8d7429b7bd9dea33d59c6e83f17372e77fe6145 Mon Sep 17 00:00:00 2001 -From: Yong Li -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 ---- - apphandler.cpp | 276 +++++++++++++++++++++++++++++++++++++- - apphandler.hpp | 1 + - host-ipmid-whitelist.conf | 1 + - 3 files changed, 274 insertions(+), 4 deletions(-) - -diff --git a/apphandler.cpp b/apphandler.cpp -index 15965ca..d8fb23d 100644 ---- a/apphandler.cpp -+++ b/apphandler.cpp -@@ -1,6 +1,19 @@ -+#include "apphandler.hpp" -+ -+#include "app/watchdog.hpp" -+#include "sys_info_param.hpp" -+#include "transporthandler.hpp" -+ - #include -+#include -+#include - #include -+#include -+#include - #include -+#include -+#include -+#include - #include - #include - -@@ -41,6 +54,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"; -@@ -59,6 +74,47 @@ using BMC = sdbusplus::xyz::openbmc_project::State::server::BMC; - namespace fs = std::filesystem; - namespace variant_ns = sdbusplus::message::variant_ns; - -+// Offset in get device id command. -+typedef struct -+{ -+ uint8_t id; -+ uint8_t revision; -+ uint8_t fw[2]; -+ uint8_t ipmi_ver; -+ uint8_t addn_dev_support; -+ uint8_t manuf_id[3]; -+ uint8_t prod_id[2]; -+ 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 data; -+} ipmiMasterRwWhitelist; -+ -+static std::vector& getWhiteList() -+{ -+ static std::vector 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 - * -@@ -1022,6 +1078,192 @@ writeResponse: - return IPMI_CC_OK; - } - -+static int loadI2CWhiteList() -+{ -+ nlohmann::json data = nullptr; -+ std::ifstream jsonFile(whiteListFilename); -+ -+ if (!jsonFile.good()) -+ { -+ log("whitelist file not found!"); -+ return -1; -+ } -+ -+ try -+ { -+ data = nlohmann::json::parse(jsonFile, nullptr, false); -+ } -+ catch (nlohmann::json::parse_error& e) -+ { -+ log("Corrupted whitelist config file", -+ entry("MSG: %s", e.what())); -+ return -1; -+ } -+ -+ try -+ { -+ unsigned int i = 0; -+ nlohmann::json filters = data[filtersStr].get(); -+ getWhiteList().resize(filters.size()); -+ -+ for (const auto& it : filters.items()) -+ { -+ nlohmann::json filter = it.value(); -+ if (filter.is_null()) -+ { -+ log("Incorrect filter"); -+ return -1; -+ } -+ -+ getWhiteList()[i].busId = -+ std::stoul(filter[busIdStr].get(), nullptr, 16); -+ -+ getWhiteList()[i].slaveAddr = std::stoul( -+ filter[slaveAddrStr].get(), nullptr, 16); -+ -+ std::string command = filter[cmdStr].get(); -+ -+ log("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("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("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(request); -+ -+ if (*data_len <= sizeof(ipmiI2cRwReq)) -+ { -+ log("Failed in request", entry("LEN=%d", *data_len)); -+ *data_len = 0; -+ return IPMI_CC_REQ_DATA_LEN_INVALID; -+ } -+ -+ if (reqi2c->readCount > maxIPMIWriteReadSize) -+ { -+ log("Failed in request", entry("R=%d", reqi2c->readCount)); -+ *data_len = 0; -+ return IPMI_CC_PARM_OUT_OF_RANGE; -+ } -+ -+ uint8_t* resptr = reinterpret_cast(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( -+ "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 inBuf(reqi2c->readCount); -+ std::vector outBuf(writeCount); -+ uint8_t* reqptr = reinterpret_cast(request); -+ -+ reqptr += sizeof(ipmiI2cRwReq); -+ std::copy(reqptr, reqptr + writeCount, outBuf.begin()); -+ -+ log("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("In whitelist"); -+ foundInList = true; -+ break; -+ } -+ } -+ -+ if (!foundInList) -+ { -+ log("Request blocked!", entry("BUS=%d", busId), -+ entry("ADDR=0x%x", reqi2c->slaveAddr)); -+ return IPMI_CC_INVALID_FIELD_REQUEST; -+ } -+ -+ log("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("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("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() - { - // -@@ -1063,6 +1306,31 @@ void register_netfn_app_functions() - ipmi_register_callback(NETFUN_APP, IPMI_CMD_GET_ACPI, NULL, - ipmi_app_get_acpi_power_state, PRIVILEGE_ADMIN); - -+// TODO: Below code and associated api's need to be removed later. -+// Its commented for now to avoid merge conflicts with upstream -+// changes and smooth upstream upgrades. -+#if 0 -+>>>>>>> IPMI Channel commands implementation -+ // -+ ipmi_register_callback(NETFUN_APP, IPMI_CMD_GET_CHANNEL_ACCESS, NULL, -+ ipmi_get_channel_access, PRIVILEGE_USER); -+ -+ // -+ ipmi_register_callback(NETFUN_APP, IPMI_CMD_GET_CHAN_INFO, NULL, -+ ipmi_app_channel_info, PRIVILEGE_USER); -+#endif -+ -+ int ret = loadI2CWhiteList(); -+ log("i2c white list is loaded", entry("RET=%d", ret), -+ entry("SIZE=%d", getWhiteList().size())); -+ if (ret == 0) -+ { -+ log("Register Master RW command"); -+ // -+ ipmi_register_callback(NETFUN_APP, IPMI_CMD_MASTER_WRITE_READ, NULL, -+ ipmiMasterWriteRead, PRIVILEGE_OPERATOR); -+ } -+ - // - 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 49ff7b0..1ae79fd 100644 ---- a/host-ipmid-whitelist.conf -+++ b/host-ipmid-whitelist.conf -@@ -27,6 +27,7 @@ - 0x06:0x37 //: - 0x06:0x42 //: - 0x06:0x4E //: -+0x06:0x52 //: - 0x06:0x54 //: - 0x0A:0x10 //: - 0x0A:0x11 //: --- -2.17.1 - diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0055-Implement-set-front-panel-button-enables-command.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0055-Implement-set-front-panel-button-enables-command.patch index 170e530f9..fd7cf1851 100644 --- a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0055-Implement-set-front-panel-button-enables-command.patch +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0055-Implement-set-front-panel-button-enables-command.patch @@ -29,12 +29,12 @@ index 4b42b3c..1a5b805 100644 static constexpr uint8_t chassisCapAddrMask = 0xfe; +static constexpr uint8_t disableResetButton = 0x2; +static constexpr uint8_t disablePowerButton = 0x1; - - typedef struct - { + static constexpr const char* powerButtonIntf = + "xyz.openbmc_project.Chassis.Buttons.Power"; + static constexpr const char* powerButtonPath = @@ -140,6 +142,19 @@ struct GetPOHCountResponse - uint8_t counterReading[4]; ///< Counter reading - } __attribute__((packed)); + uint8_t front_panel_button_cap_status; + } __attribute__((packed)) ipmi_get_chassis_status_t; +typedef struct +{ @@ -52,17 +52,8 @@ index 4b42b3c..1a5b805 100644 // Phosphor Host State manager namespace State = sdbusplus::xyz::openbmc_project::State::server; -@@ -948,6 +963,8 @@ ipmi_ret_t ipmi_get_chassis_status(ipmi_netfn_t netfn, ipmi_cmd_t cmd, - - // Front Panel Button Capabilities and disable/enable status(Optional) - // set to 0, for we don't support them. -+ // TODO, it is tracked by an issue: -+ // https://github.com/openbmc/phosphor-host-ipmid/issues/122 - chassis_status.front_panel_button_cap_status = 0; - - // Pack the actual response @@ -1721,6 +1738,82 @@ ipmi_ret_t ipmi_chassis_set_power_restore_policy( - return IPMI_CC_OK; + return ipmi::responseSuccess(power_policy::allSupport); } +ipmi_ret_t ipmiSetFrontPanelButtonEnables(ipmi_netfn_t netfn, ipmi_cmd_t cmd, @@ -161,7 +152,7 @@ index 49b5ef8..f4a6bff 100644 --- a/chassishandler.hpp +++ b/chassishandler.hpp @@ -19,6 +19,7 @@ enum ipmi_netfn_chassis_cmds - // 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_SET_FRONT_PANEL_BUTTON_ENABLES = 0x0A, @@ -173,13 +164,13 @@ index e5cd0b5..d96d9ed 100644 --- a/host-ipmid-whitelist.conf +++ b/host-ipmid-whitelist.conf @@ -6,6 +6,7 @@ - 0x00:0x06 //: + 0x00:0x07 //: 0x00:0x08 //: 0x00:0x09 //: +0x00:0x0A //: 0x00:0x0F //: + 0x04:0x02 //: 0x04:0x2D //: - 0x04:0x2F //: -- 2.19.1 diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0057-Add-timer-use-actions-support.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0057-Add-timer-use-actions-support.patch index 5813cceae..a96707d44 100644 --- a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0057-Add-timer-use-actions-support.patch +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0057-Add-timer-use-actions-support.patch @@ -144,14 +144,14 @@ index e65ea63..8b1aa47 100644 +++ b/app/watchdog_service.cpp @@ -83,6 +83,9 @@ WatchdogService::Properties WatchdogService::getProperties() wd_prop.timerUse = Watchdog::convertTimerUseFromString( - get(properties.at("CurrentTimerUse"))); + std::get(properties.at("CurrentTimerUse"))); + wd_prop.expiredTimerUse = Watchdog::convertTimerUseFromString( -+ get(properties.at("ExpiredTimerUse"))); ++ std::get(properties.at("ExpiredTimerUse"))); + - wd_prop.interval = get(properties.at("Interval")); - wd_prop.timeRemaining = get(properties.at("TimeRemaining")); - return wd_prop; + wd_prop.interval = std::get(properties.at("Interval")); + wd_prop.timeRemaining = + std::get(properties.at("TimeRemaining")); @@ -187,6 +190,11 @@ void WatchdogService::setTimerUse(TimerUse timerUse) setProperty("CurrentTimerUse", convertForMessage(timerUse)); } diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0060-Move-Get-SOL-config-parameter-to-host-ipmid.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0060-Move-Get-SOL-config-parameter-to-host-ipmid.patch index 49a2c01ba..24f355d80 100644 --- a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0060-Move-Get-SOL-config-parameter-to-host-ipmid.patch +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0060-Move-Get-SOL-config-parameter-to-host-ipmid.patch @@ -1,43 +1,93 @@ -From 973865687325c6563fd6b729a3a220661066f635 Mon Sep 17 00:00:00 2001 +From 3c95de833eba73b3585941ade42ad1775e723280 Mon Sep 17 00:00:00 2001 From: Cheng C Yang -Date: Wed, 3 Apr 2019 15:55:04 +0800 +Date: Tue, 7 May 2019 08:03:56 +0800 Subject: [PATCH] Move Get SOL config parameter to host-ipmid Move Get SOL config parameter command from net-ipmid to host-ipmid. -Tested By: +Tested: Run command ipmitool sol info Set in progress : set-complete Enabled : true Force Encryption : false Force Authentication : false -Privilege Level : USER -Character Accumulate Level (ms) : 100 -Character Send Threshold : 1 -Retry Count : 3 -Retry Interval (ms) : 100 +Privilege Level : ADMINISTRATOR +Character Accumulate Level (ms) : 60 +Character Send Threshold : 96 +Retry Count : 6 +Retry Interval (ms) : 200 Volatile Bit Rate (kbps) : IPMI-Over-Serial-Setting -Non-Volatile Bit Rate (kbps) : IPMI-Over-Serial-Setting +Non-Volatile Bit Rate (kbps) : 115.2 Payload Channel : 14 (0x0e) Payload Port : 623 Signed-off-by: Cheng C Yang --- - transporthandler.cpp | 139 ++++++++++++++++++++++++++++++++++++++++++++++++--- - transporthandler.hpp | 26 +++++++++- - 2 files changed, 156 insertions(+), 9 deletions(-) + host-ipmid-whitelist.conf | 1 + + transporthandler.cpp | 198 ++++++++++++++++++++++++++++++++++++++++++++-- + transporthandler.hpp | 27 ++++++- + 3 files changed, 217 insertions(+), 9 deletions(-) +diff --git a/host-ipmid-whitelist.conf b/host-ipmid-whitelist.conf +index 2ce44c6..383b412 100644 +--- a/host-ipmid-whitelist.conf ++++ b/host-ipmid-whitelist.conf +@@ -43,6 +43,7 @@ + 0x0A:0x49 //: + 0x0C:0x02 //: + 0x0C:0x21 //: ++0x0C:0x22 //: + 0x2C:0x00 //: + 0x2C:0x01 //: + 0x2C:0x02 //: diff --git a/transporthandler.cpp b/transporthandler.cpp -index 2111acf..b18f522 100644 +index 850172d..0c1223a 100644 --- a/transporthandler.cpp +++ b/transporthandler.cpp -@@ -1715,11 +1715,133 @@ void initializeSOLInProgress() +@@ -38,6 +38,8 @@ static const std::array ipAddressEnablesType = { + + constexpr const char* solInterface = "xyz.openbmc_project.Ipmi.SOL"; + constexpr const char* solPath = "/xyz/openbmc_project/ipmi/sol"; ++constexpr const char* consoleInterface = "xyz.openbmc_project.console"; ++constexpr const char* consolePath = "/xyz/openbmc_project/console"; + + std::map> channelConfig; + +@@ -1668,6 +1670,26 @@ static int setSOLParameter(std::string property, const ipmi::Value& value) + return 0; + } + ++static int getSOLBaudRate(ipmi::Value& value) ++{ ++ auto dbus = getSdBus(); ++ ++ try ++ { ++ value = ++ ipmi::getDbusProperty(*dbus, "xyz.openbmc_project.console", ++ consolePath, consoleInterface, "baudrate"); ++ } ++ catch (sdbusplus::exception_t&) ++ { ++ phosphor::logging::log( ++ "Error getting sol baud rate"); ++ return -1; ++ } ++ ++ return 0; ++} ++ + static int getSOLParameter(std::string property, ipmi::Value& value) + { + auto dbus = getSdBus(); +@@ -1711,11 +1733,170 @@ void initializeSOLInProgress() } } -ipmi_ret_t setConfParams(ipmi_netfn_t netfn, ipmi_cmd_t cmd, - ipmi_request_t request, ipmi_response_t response, - ipmi_data_len_t dataLen, ipmi_context_t context) ++static const constexpr uint8_t retryCountMask = 0x07; +// For getsetSOLConfParams, there are still three tings TODO: +// 1. session less channel number request has to return error. +// 2. convert 0xE channel number. @@ -45,8 +95,7 @@ index 2111acf..b18f522 100644 +ipmi_ret_t getSOLConfParams(ipmi_netfn_t netfn, ipmi_cmd_t cmd, + ipmi_request_t request, ipmi_response_t response, + ipmi_data_len_t dataLen, ipmi_context_t context) - { -- auto reqData = reinterpret_cast(request); ++{ + auto reqData = reinterpret_cast(request); + std::vector outPayload; + @@ -134,7 +183,7 @@ index 2111acf..b18f522 100644 + { + return IPMI_CC_UNSPECIFIED_ERROR; + } -+ outPayload.push_back(std::get(value) & 0x03); ++ outPayload.push_back(std::get(value) & retryCountMask); + + if (getSOLParameter("RetryIntervalMS", value) < 0) + { @@ -151,6 +200,42 @@ index 2111acf..b18f522 100644 + std::back_inserter(outPayload)); + break; + } ++ case sol::Parameter::nvbitrate: ++ { ++ if (getSOLBaudRate(value) < 0) ++ { ++ return IPMI_CC_UNSPECIFIED_ERROR; ++ } ++ uint8_t bitRate = 0; ++ uint32_t* pBaudRate = std::get_if(&value); ++ if (!pBaudRate) ++ { ++ phosphor::logging::log( ++ "Failed to get valid baud rate from D-Bus interface"); ++ } ++ switch (*pBaudRate) ++ { ++ case 9600: ++ bitRate = 0x06; ++ break; ++ case 19200: ++ bitRate = 0x07; ++ break; ++ case 38400: ++ bitRate = 0x08; ++ break; ++ case 57600: ++ bitRate = 0x09; ++ break; ++ case 115200: ++ bitRate = 0x0a; ++ break; ++ default: ++ break; ++ } ++ outPayload.push_back(bitRate); ++ break; ++ } + default: + return IPMI_CC_PARM_NOT_SUPPORTED; + } @@ -164,12 +249,13 @@ index 2111acf..b18f522 100644 +ipmi_ret_t setSOLConfParams(ipmi_netfn_t netfn, ipmi_cmd_t cmd, + ipmi_request_t request, ipmi_response_t response, + ipmi_data_len_t dataLen, ipmi_context_t context) -+{ + { +- auto reqData = reinterpret_cast(request); + auto reqData = reinterpret_cast(request); // Check request length first switch (static_cast(reqData->paramSelector)) -@@ -1728,7 +1850,7 @@ ipmi_ret_t setConfParams(ipmi_netfn_t netfn, ipmi_cmd_t cmd, +@@ -1724,7 +1905,7 @@ ipmi_ret_t setConfParams(ipmi_netfn_t netfn, ipmi_cmd_t cmd, case sol::Parameter::enable: case sol::Parameter::authentication: { @@ -178,7 +264,7 @@ index 2111acf..b18f522 100644 { *dataLen = 0; return IPMI_CC_REQ_DATA_LEN_INVALID; -@@ -1738,7 +1860,7 @@ ipmi_ret_t setConfParams(ipmi_netfn_t netfn, ipmi_cmd_t cmd, +@@ -1734,7 +1915,7 @@ ipmi_ret_t setConfParams(ipmi_netfn_t netfn, ipmi_cmd_t cmd, case sol::Parameter::accumulate: case sol::Parameter::retry: { @@ -187,7 +273,7 @@ index 2111acf..b18f522 100644 { *dataLen = 0; return IPMI_CC_REQ_DATA_LEN_INVALID; -@@ -1869,7 +1991,10 @@ void register_netfn_transport_functions() +@@ -1865,7 +2046,10 @@ void register_netfn_transport_functions() ipmi_transport_get_lan, PRIVILEGE_OPERATOR); ipmi_register_callback(NETFUN_TRANSPORT, IPMI_CMD_SET_SOL_CONF_PARAMS, NULL, @@ -200,10 +286,18 @@ index 2111acf..b18f522 100644 // Initialize dbus property progress to 0 every time sol manager restart. initializeSOLInProgress(); diff --git a/transporthandler.hpp b/transporthandler.hpp -index 3b5e9e1..7132cff 100644 +index 3b5e9e1..a21862b 100644 --- a/transporthandler.hpp +++ b/transporthandler.hpp -@@ -257,7 +257,7 @@ struct Retry +@@ -1,6 +1,7 @@ + #pragma once + + #include ++#include + #include + // IPMI commands for Transport net functions. + enum ipmi_netfn_storage_cmds +@@ -257,7 +258,7 @@ struct Retry uint8_t interval; //!< SOL retry interval. } __attribute__((packed)); @@ -212,7 +306,7 @@ index 3b5e9e1..7132cff 100644 { #if BYTE_ORDER == LITTLE_ENDIAN uint8_t channelNumber : 4; //!< Channel number. -@@ -279,7 +279,29 @@ struct SetConfParamsRequest +@@ -279,7 +280,29 @@ struct SetConfParamsRequest }; } __attribute__((packed)); @@ -244,5 +338,5 @@ index 3b5e9e1..7132cff 100644 +static constexpr uint16_t ipmiStdPort = 623; +static constexpr uint8_t solParameterRevision = 0x11; -- -2.16.2 +2.7.4 diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host_%.bbappend b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host_%.bbappend index f454f7ce9..91319a9d3 100644 --- a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host_%.bbappend +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host_%.bbappend @@ -3,27 +3,37 @@ FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:" # TODO: This should be removed, once up-stream bump up # issue is resolved #SRC_URI = "git://github.com/openbmc/phosphor-host-ipmid" -SRCREV = "11df4f6906edc0dfb23089a6e297158549c19ebd" +SRCREV = "fdb8389df74f9f0d6428252a75c33f6abf6d8481" 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://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://0053-Fix-keep-looping-issue-when-entering-OS.patch \ file://0055-Implement-set-front-panel-button-enables-command.patch \ file://0056-add-SetInProgress-to-get-set-boot-option-cmd.patch \ file://0057-Add-timer-use-actions-support.patch \ - file://0058-Add-AC-failed-bit-support-for-get-chassis-status-com.patch \ file://0059-Move-Set-SOL-config-parameter-to-host-ipmid.patch \ file://0060-Move-Get-SOL-config-parameter-to-host-ipmid.patch \ " +# remove the softpoweroff service since we do not need it +SYSTEMD_SERVICE_${PN}_remove += " \ + xyz.openbmc_project.Ipmi.Internal.SoftPowerOff.service" + +SYSTEMD_LINK_${PN}_remove += " \ + ../xyz.openbmc_project.Ipmi.Internal.SoftPowerOff.service:obmc-host-shutdown@0.target.requires/xyz.openbmc_project.Ipmi.Internal.SoftPowerOff.service \ + " +FILES_${PN}_remove = " \ + ${systemd_unitdir}/system/obmc-host-shutdown@0.target.requires/ \ + ${systemd_unitdir}/system/obmc-host-shutdown@0.target.requires/xyz.openbmc_project.Ipmi.Internal.SoftPowerOff.service \ + " + +do_install_append(){ + rm -f ${D}/${bindir}/phosphor-softpoweroff +} diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-ipmb_%.bbappend b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-ipmb_%.bbappend index 694bd1fcf..13d908ad1 100644 --- 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 @@ -1,2 +1,2 @@ SRC_URI = "git://github.com/openbmc/ipmbbridge.git" -SRCREV = "08deaa317c7ac0dd6e4202529ff17962c63df485" +SRCREV = "8188d7651c23502f88f9bf850ab7e549f6463997" 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 deleted file mode 100644 index 288fa422d..000000000 --- a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-kcs/org.openbmc.HostIpmi.SMM.service +++ /dev/null @@ -1,13 +0,0 @@ -[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 deleted file mode 100644 index 177062e27..000000000 --- a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-kcs/org.openbmc.HostIpmi.service +++ /dev/null @@ -1,13 +0,0 @@ -[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 index ac7a03108..e3d397f06 100644 --- 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 @@ -1,9 +1,12 @@ FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:" -DBUS_SERVICE_${PN} += "org.openbmc.HostIpmi.SMM.service" +#SYSTEMD_SUBSTITUTIONS_remove = "KCS_DEVICE:${KCS_DEVICE}:${DBUS_SERVICE_${PN}}" -SYSTEMD_SUBSTITUTIONS_remove = "KCS_DEVICE:${KCS_DEVICE}:${DBUS_SERVICE_${PN}}" +# Default kcs device is ipmi-kcs3; this is SMS. +# Add SMM kcs device instance +SMM_DEVICE = "ipmi-kcs4" +SYSTEMD_SERVICE_${PN}_append = " ${PN}@${SMM_DEVICE}.service " SRC_URI = "git://github.com/openbmc/kcsbridge.git" -SRCREV = "17a2ab7f39a78ff0603aa68cf35108ea94eb442f" +SRCREV = "2cdc49585235a6557c9cbb6c8b75c064fc02681a" 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 index 6212c0724..c6b87bf4f 100644 --- 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 @@ -256,54 +256,24 @@ 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 +@@ -107,14 +107,15 @@ class Channel * -+ * @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 + * @return A uint32_t representation of the remote IPv4 address */ - std::uint32_t getRemoteAddressInbytes() -+ auto getPort() const ++ uint32_t getRemoteAddressInBytes() const { - const boost::asio::ip::address& addr = endpoint.address(); - if (addr.is_v4()) -- { ++ uint32_t v4addr = 0; ++ if (sockAddrSize == sizeof(sockaddr_in)) + { - return addr.to_v4().to_uint(); -- } ++ auto saddr = reinterpret_cast(&remoteSockAddr); ++ v4addr = ntohl(saddr->sin_addr.s_addr); + } - return 0; -+ return endpoint.port(); ++ return v4addr; } /** diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-net/0011-Remove-Get-SOL-Config-Command-from-Netipmid.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-net/0011-Remove-Get-SOL-Config-Command-from-Netipmid.patch new file mode 100644 index 000000000..da173704b --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-net/0011-Remove-Get-SOL-Config-Command-from-Netipmid.patch @@ -0,0 +1,336 @@ +From a36f181163974b2da0a954fc97a89fb2cdbd7287 Mon Sep 17 00:00:00 2001 +From: Cheng C Yang +Date: Tue, 30 Apr 2019 05:35:31 +0800 +Subject: [PATCH] Remove Get SOL Config Command from Netipmid + +Since Get SOL Config Parameter command already exists in host-ipmid, and +can be shared to net channel, remove this command from net-ipmid. + +Tested: +Run ipmitool -I lanplus -H xxx -U root -P 0penBmc sol info, the command +returns the same result as ipmitool sol info as below. +Info: SOL parameter 'Nonvolatile Bitrate (5)' not supported +Info: SOL parameter 'Volatile Bitrate (6)' not supported +Info: SOL parameter 'Payload Channel (7)' not supported - defaulting to 0x0e +Set in progress : set-complete +Enabled : true +Force Encryption : true +Force Authentication : true +Privilege Level : USER +Character Accumulate Level (ms) : 100 +Character Send Threshold : 1 +Retry Count : 3 +Retry Interval (ms) : 100 +Volatile Bit Rate (kbps) : IPMI-Over-Serial-Setting +Non-Volatile Bit Rate (kbps) : IPMI-Over-Serial-Setting +Payload Channel : 14 (0x0e) +Payload Port : 623 + +Signed-off-by: Cheng C Yang +--- + command/sol_cmds.cpp | 91 ---------------------------- + command/sol_cmds.hpp | 168 --------------------------------------------------- + sol_module.cpp | 6 -- + 3 files changed, 265 deletions(-) + +diff --git a/command/sol_cmds.cpp b/command/sol_cmds.cpp +index 804b5ea..8b2d041 100644 +--- a/command/sol_cmds.cpp ++++ b/command/sol_cmds.cpp +@@ -65,97 +65,6 @@ void activating(uint8_t payloadInstance, uint32_t sessionID) + outPayload); + } + +-std::vector getConfParams(const std::vector& inPayload, +- const message::Handler& handler) +-{ +- std::vector outPayload(sizeof(GetConfParamsResponse)); +- auto request = +- reinterpret_cast(inPayload.data()); +- auto response = reinterpret_cast(outPayload.data()); +- response->completionCode = IPMI_CC_OK; +- response->paramRev = parameterRevision; +- +- if (request->getParamRev) +- { +- return outPayload; +- } +- +- switch (static_cast(request->paramSelector)) +- { +- case Parameter::PROGRESS: +- { +- outPayload.push_back( +- std::get(singletonPool).progress); +- break; +- } +- case Parameter::ENABLE: +- { +- outPayload.push_back(std::get(singletonPool).enable); +- break; +- } +- case Parameter::AUTHENTICATION: +- { +- Auth value{0}; +- +- value.encrypt = std::get(singletonPool).forceEncrypt; +- value.auth = std::get(singletonPool).forceAuth; +- value.privilege = static_cast( +- std::get(singletonPool).solMinPrivilege); +- auto buffer = reinterpret_cast(&value); +- +- std::copy_n(buffer, sizeof(value), std::back_inserter(outPayload)); +- break; +- } +- case Parameter::ACCUMULATE: +- { +- Accumulate value{0}; +- +- value.interval = std::get(singletonPool) +- .accumulateInterval.count() / +- sol::accIntervalFactor; +- value.threshold = +- std::get(singletonPool).sendThreshold; +- auto buffer = reinterpret_cast(&value); +- +- std::copy_n(buffer, sizeof(value), std::back_inserter(outPayload)); +- break; +- } +- case Parameter::RETRY: +- { +- Retry value{0}; +- +- value.count = std::get(singletonPool).retryCount; +- value.interval = +- std::get(singletonPool).retryInterval.count() / +- sol::retryIntervalFactor; +- auto buffer = reinterpret_cast(&value); +- +- std::copy_n(buffer, sizeof(value), std::back_inserter(outPayload)); +- break; +- } +- case Parameter::PORT: +- { +- auto port = endian::to_ipmi(IPMI_STD_PORT); +- auto buffer = reinterpret_cast(&port); +- +- std::copy_n(buffer, sizeof(port), std::back_inserter(outPayload)); +- break; +- } +- case Parameter::CHANNEL: +- { +- outPayload.push_back( +- std::get(singletonPool).channel); +- break; +- } +- case Parameter::NVBITRATE: +- case Parameter::VBITRATE: +- default: +- response->completionCode = ipmiCCParamNotSupported; +- } +- +- return outPayload; +-} +- + } // namespace command + + } // namespace sol +diff --git a/command/sol_cmds.hpp b/command/sol_cmds.hpp +index 182b73e..10cbf25 100644 +--- a/command/sol_cmds.hpp ++++ b/command/sol_cmds.hpp +@@ -62,174 +62,6 @@ struct ActivatingRequest + */ + void activating(uint8_t payloadInstance, uint32_t sessionID); + +-/** @enum Parameter +- * +- * SOL parameters are volatile, they are initialized by the SOL manager. +- * They can be read using Get SOL configuration parameters command and updated +- * using Set SOL configuration parameters command. +- */ +-enum class Parameter +-{ +- PROGRESS, //!< Set In Progress. +- ENABLE, //!< SOL Enable. +- AUTHENTICATION, //!< SOL Authentication. +- ACCUMULATE, //!< Character Accumulate Interval & Send Threshold. +- RETRY, //!< SOL Retry. +- NVBITRATE, //!< SOL non-volatile bit rate. +- VBITRATE, //!< SOL volatile bit rate. +- CHANNEL, //!< SOL payload channel. +- PORT, //!< SOL payload port. +-}; +- +-constexpr uint8_t progressMask = 0x03; +-constexpr uint8_t enableMask = 0x01; +- +-/** @struct Auth +- * +- * SOL authentication parameter. +- */ +-struct Auth +-{ +-#if BYTE_ORDER == LITTLE_ENDIAN +- uint8_t privilege : 4; //!< SOL privilege level. +- uint8_t reserved : 2; //!< Reserved. +- uint8_t auth : 1; //!< Force SOL payload Authentication. +- uint8_t encrypt : 1; //!< Force SOL payload encryption. +-#endif +- +-#if BYTE_ORDER == BIG_ENDIAN +- uint8_t encrypt : 1; //!< Force SOL payload encryption. +- uint8_t auth : 1; //!< Force SOL payload Authentication. +- uint8_t reserved : 2; //!< Reserved. +- uint8_t privilege : 4; //!< SOL privilege level. +-#endif +-} __attribute__((packed)); +- +-/** @struct Accumulate +- * +- * Character accumulate interval & Character send threshold. +- */ +-struct Accumulate +-{ +- uint8_t interval; //!< Character accumulate interval. +- uint8_t threshold; //!< Character send threshold. +-} __attribute__((packed)); +- +-constexpr uint8_t retryCountMask = 0x07; +- +-/** @struct Retry +- * +- * SOL retry count and interval. +- */ +-struct Retry +-{ +-#if BYTE_ORDER == LITTLE_ENDIAN +- uint8_t count : 3; //!< SOL retry count. +- uint8_t reserved : 5; //!< Reserved. +-#endif +- +-#if BYTE_ORDER == BIG_ENDIAN +- uint8_t reserved : 5; //!< Reserved. +- uint8_t count : 3; //!< SOL retry count. +-#endif +- +- uint8_t interval; //!< SOL retry interval. +-} __attribute__((packed)); +- +-constexpr uint8_t ipmiCCParamNotSupported = 0x80; +-constexpr uint8_t ipmiCCInvalidSetInProgress = 0x81; +-constexpr uint8_t ipmiCCWriteReadParameter = 0x82; +-constexpr uint8_t ipmiCCReadWriteParameter = 0x83; +-constexpr uint8_t parameterRevision = 0x11; +- +-/** @struct SetConfParamsRequest +- * +- * IPMI payload for Set SOL configuration parameters command request. +- */ +-struct SetConfParamsRequest +-{ +-#if BYTE_ORDER == LITTLE_ENDIAN +- uint8_t channelNumber : 4; //!< Channel number. +- uint8_t reserved : 4; //!< Reserved. +-#endif +- +-#if BYTE_ORDER == BIG_ENDIAN +- uint8_t reserved : 4; //!< Reserved. +- uint8_t channelNumber : 4; //!< Channel number. +-#endif +- +- uint8_t paramSelector; //!< Parameter selector. +- union +- { +- uint8_t value; //!< Represents one byte SOL parameters. +- struct Accumulate acc; //!< Character accumulate values. +- struct Retry retry; //!< Retry values. +- struct Auth auth; //!< Authentication parameters. +- }; +-} __attribute__((packed)); +- +-/** @struct SetConfParamsResponse +- * +- * IPMI payload for Set SOL configuration parameters command response. +- */ +-struct SetConfParamsResponse +-{ +- uint8_t completionCode; //!< Completion code. +-} __attribute__((packed)); +- +-/** @brief Set SOL configuration parameters command. +- * +- * @param[in] inPayload - Request data for the command. +- * @param[in] handler - Reference to the message handler. +- * +- * @return Response data for the command. +- */ +-std::vector setConfParams(const std::vector& inPayload, +- const message::Handler& handler); +- +-/** @struct GetConfParamsRequest +- * +- * IPMI payload for Get SOL configuration parameters command request. +- */ +-struct GetConfParamsRequest +-{ +-#if BYTE_ORDER == LITTLE_ENDIAN +- uint8_t channelNum : 4; //!< Channel number. +- uint8_t reserved : 3; //!< Reserved. +- uint8_t getParamRev : 1; //!< Get parameter or Get parameter revision +-#endif +- +-#if BYTE_ORDER == BIG_ENDIAN +- uint8_t getParamRev : 1; //!< Get parameter or Get parameter revision +- uint8_t reserved : 3; //!< Reserved. +- uint8_t channelNum : 4; //!< Channel number. +-#endif +- +- uint8_t paramSelector; //!< Parameter selector. +- uint8_t setSelector; //!< Set selector. +- uint8_t blockSelector; //!< Block selector. +-} __attribute__((packed)); +- +-/** @struct GetConfParamsResponse +- * +- * IPMI payload for Get SOL configuration parameters command response. +- */ +-struct GetConfParamsResponse +-{ +- uint8_t completionCode; //!< Completion code. +- uint8_t paramRev; //!< Parameter revision. +-} __attribute__((packed)); +- +-/** @brief Get SOL configuration parameters command. +- * +- * @param[in] inPayload - Request data for the command. +- * @param[in] handler - Reference to the message handler. +- * +- * @return Response data for the command. +- */ +-std::vector getConfParams(const std::vector& inPayload, +- const message::Handler& handler); +- + } // namespace command + + } // namespace sol +diff --git a/sol_module.cpp b/sol_module.cpp +index 2b1fb46..6da82c0 100644 +--- a/sol_module.cpp ++++ b/sol_module.cpp +@@ -42,12 +42,6 @@ void registerCommands() + &getPayloadInfo, + session::Privilege::USER, + false}, +- // Get SOL Configuration Parameters +- {{(static_cast(message::PayloadType::IPMI) << 16) | +- static_cast(::command::NetFns::TRANSPORT) | 0x22}, +- &getConfParams, +- session::Privilege::USER, +- false}, + }; + + for (const auto& iter : commands) +-- +2.7.4 + diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-net_%.bbappend b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-net_%.bbappend index 9dc21a3dd..9f5e3fa6f 100644 --- a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-net_%.bbappend +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-net_%.bbappend @@ -3,12 +3,20 @@ inherit useradd # TODO: This should be removed, once up-stream bump up # issue is resolved #SRC_URI += "git://github.com/openbmc/phosphor-net-ipmid" -#SRCREV = "8af90ebcc552e243ae85aa9e9da1a00fbecab56c" +#SRCREV = "052b7cf37411a1bb69af1e6ce541a16021fffa9f" USERADD_PACKAGES = "${PN}" # add a group called ipmi GROUPADD_PARAM_${PN} = "ipmi " +# Default rmcpp iface is eth0; channel 1 +# Add channel 2 instance (eth1) +RMCPP_EXTRA = "eth1" +SYSTEMD_SERVICE_${PN} += " \ + ${PN}@${RMCPP_EXTRA}.service \ + ${PN}@${RMCPP_EXTRA}.socket \ + " + FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:" SRC_URI += " file://0006-Modify-dbus-namespace-of-chassis-control-for-guid.patch \ @@ -16,5 +24,6 @@ SRC_URI += " file://0006-Modify-dbus-namespace-of-chassis-control-for-guid.patch file://0008-Sync-GetSession-Info-cmd-based-on-Upstream-review.patch \ file://0009-Add-dbus-interface-for-sol-commands.patch \ file://00010-Change-Authentication-Parameter.patch \ + file://0011-Remove-Get-SOL-Config-Command-from-Netipmid.patch \ " 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 index af83facf6..4861755b6 100644 --- 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 @@ -2,7 +2,7 @@ SUMMARY = "Node Manager Proxy" DESCRIPTION = "The Node Manager Proxy provides a simple interface for communicating \ with Management Engine via IPMB" -SRC_URI = "git://git@github.com/Intel-BMC/node-manager;protocol=ssh" +SRC_URI = "git://github.com/Intel-BMC/node-manager;protocol=ssh" SRCREV = "2ab90332828614c95e0ce22c0c95285734b55b65" PV = "0.1+git${SRCPV}" -- cgit v1.2.3