summaryrefslogtreecommitdiffstats
path: root/dcmihandler.cpp
diff options
context:
space:
mode:
authorDhruvaraj Subhashchandran <dhruvaraj@in.ibm.com>2018-01-16 05:11:56 -0600
committerTom Joseph <tomjoseph@in.ibm.com>2018-01-31 09:13:20 +0000
commite29be41f1d014a55e93abd3e55ac23f158f5fa16 (patch)
treef084ca93eb46ef2545fc2e95abef384d1fbd0d84 /dcmihandler.cpp
parent9642391d3953754761d5312f59ecbc90341b4759 (diff)
downloadphosphor-host-ipmid-e29be41f1d014a55e93abd3e55ac23f158f5fa16.tar.gz
phosphor-host-ipmid-e29be41f1d014a55e93abd3e55ac23f158f5fa16.zip
DCMI: Implement Get DCMI capabilities info command.
This commit adds ipmi changes for supporting the get DCMI capabilities command Resolves openbmc/openbmc#2618 Change-Id: I7d0e7c132f4a8d459351e025fa2bfca9fcf1340b Signed-off-by: Dhruvaraj Subhashchandran <dhruvaraj@in.ibm.com>
Diffstat (limited to 'dcmihandler.cpp')
-rw-r--r--dcmihandler.cpp131
1 files changed, 131 insertions, 0 deletions
diff --git a/dcmihandler.cpp b/dcmihandler.cpp
index ab3aa58..aa9f14e 100644
--- a/dcmihandler.cpp
+++ b/dcmihandler.cpp
@@ -7,6 +7,9 @@
#include <stdio.h>
#include <string.h>
#include <stdint.h>
+#include <fstream>
+#include <bitset>
+#include "nlohmann/json.hpp"
#include "xyz/openbmc_project/Common/error.hpp"
using namespace phosphor::logging;
@@ -21,6 +24,11 @@ constexpr auto PCAP_INTERFACE = "xyz.openbmc_project.Control.Power.Cap";
constexpr auto POWER_CAP_PROP = "PowerCap";
constexpr auto POWER_CAP_ENABLE_PROP = "PowerCapEnable";
+constexpr auto DCMI_PARAMETER_REVISION = 2;
+constexpr auto DCMI_SPEC_MAJOR_VERSION = 1;
+constexpr auto DCMI_SPEC_MINOR_VERSION = 5;
+constexpr auto DCMI_CAP_JSON_FILE = "/usr/share/ipmi-providers/dcmi_cap.json";
+
using namespace phosphor::logging;
namespace dcmi
@@ -603,6 +611,126 @@ ipmi_ret_t setMgmntCtrlIdStr(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
return IPMI_CC_OK;
}
+//List of the capabilities under each parameter
+dcmi::DCMICaps dcmiCaps =
+{
+//Supported DCMI Capabilities
+ {
+ dcmi::DCMICapParameters::SUPPORTED_DCMI_CAPS,
+ {
+ 3, {{"PowerManagement", 2, 0, 1},
+ {"OOBSecondaryLan", 3, 2, 1},
+ {"SerialTMODE", 3, 1, 1},
+ {"InBandSystemInterfaceChannel", 3, 0, 1}
+ }
+ }
+ },
+//Mandatory Platform Attributes
+ {
+ dcmi::DCMICapParameters::MANDATORY_PLAT_ATTRIBUTES,
+ {
+ 5, {{"SELAutoRollOver", 1, 15, 1},
+ {"FlushEntireSELUponRollOver", 1, 14, 1},
+ {"RecordLevelSELFlushUponRollOver", 1, 13, 1},
+ {"NumberOfSELEntries", 1, 0, 12},
+ {"TempMonitoringSamplingFreq", 5, 0, 8}
+ }
+ }
+ },
+//Optional Platform Attributes
+ {
+ dcmi::DCMICapParameters::OPTIONAL_PLAT_ATTRIBUTES,
+ {
+ 2, {{"PowerMgmtDeviceSlaveAddress", 1, 1, 7},
+ {"BMCChannelNumber", 2, 4, 4},
+ {"DeviceRivision", 2, 0, 4}
+ }
+ }
+ },
+//Manageability Access Attributes
+ {
+ dcmi::DCMICapParameters::MANAGEABILITY_ACCESS_ATTRIBUTES,
+ {
+ 3, {{"MandatoryPrimaryLanOOBSupport", 1, 0, 8},
+ {"OptionalSecondaryLanOOBSupport", 2, 0, 8},
+ {"OptionalSerialOOBMTMODECapability", 3, 0, 8}
+ }
+ }
+ }
+};
+
+ipmi_ret_t getDCMICapabilities(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)
+{
+
+ std::ifstream dcmiCapFile(DCMI_CAP_JSON_FILE);
+ if (!dcmiCapFile.is_open())
+ {
+ log<level::ERR>("DCMI Capabilities file not found");
+ return IPMI_CC_UNSPECIFIED_ERROR;
+ }
+
+ auto data = nlohmann::json::parse(dcmiCapFile, nullptr, false);
+ if (data.is_discarded())
+ {
+ log<level::ERR>("DCMI Capabilities JSON parser failure");
+ return IPMI_CC_UNSPECIFIED_ERROR;
+ }
+
+ auto requestData = reinterpret_cast<const dcmi::GetDCMICapRequest*>
+ (request);
+
+ //get list of capabilities in a parameter
+ auto caps =
+ dcmiCaps.find(static_cast<dcmi::DCMICapParameters>(requestData->param));
+ if (caps == dcmiCaps.end())
+ {
+ log<level::ERR>("Invalid input parameter");
+ return IPMI_CC_INVALID_FIELD_REQUEST;
+ }
+
+ if (requestData->groupID != dcmi::groupExtId)
+ {
+ *data_len = 0;
+ return IPMI_CC_INVALID_FIELD_REQUEST;
+ }
+
+ auto responseData = reinterpret_cast<dcmi::GetDCMICapResponse*>
+ (response);
+
+ //For each capabilities in a parameter fill the data from
+ //the json file based on the capability name.
+ for (auto cap : caps->second.capList)
+ {
+ //If the data is beyond first byte boundary, insert in a
+ //16bit pattern for example number of SEL entries are represented
+ //in 12bits.
+ if ((cap.length + cap.position) > 8)
+ {
+ //Read the value corresponding to capability name and assign to
+ //16bit bitset.
+ std::bitset<16> val(data.value(cap.name.c_str(), 0));
+ val <<= cap.position;
+ reinterpret_cast<uint16_t*>(responseData->data)[
+ (cap.bytePosition - 1) / sizeof(uint16_t)] |= val.to_ulong();
+ }
+ else
+ {
+ responseData->data[cap.bytePosition - 1] |=
+ data.value(cap.name.c_str(), 0) << cap.position;
+ }
+ }
+
+ responseData->groupID = dcmi::groupExtId;
+ responseData->major = DCMI_SPEC_MAJOR_VERSION;
+ responseData->minor = DCMI_SPEC_MINOR_VERSION;
+ responseData->paramRevision = DCMI_PARAMETER_REVISION;
+ *data_len = sizeof(*responseData) + caps->second.size;
+
+ return IPMI_CC_OK;
+}
+
void register_netfn_dcmi_functions()
{
// <Get Power Limit>
@@ -653,6 +781,9 @@ void register_netfn_dcmi_functions()
ipmi_register_callback(NETFUN_GRPEXT, dcmi::Commands::SET_MGMNT_CTRL_ID_STR,
NULL, setMgmntCtrlIdStr, PRIVILEGE_ADMIN);
+ // <Get DCMI capabilities>
+ ipmi_register_callback(NETFUN_GRPEXT, dcmi::Commands::GET_CAPABILITIES,
+ NULL, getDCMICapabilities, PRIVILEGE_USER);
return;
}
// 956379
OpenPOWER on IntegriCloud