summaryrefslogtreecommitdiff
path: root/lib/ipmi_dcmi.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ipmi_dcmi.c')
-rwxr-xr-xlib/ipmi_dcmi.c2238
1 files changed, 1968 insertions, 270 deletions
diff --git a/lib/ipmi_dcmi.c b/lib/ipmi_dcmi.c
index 6e030f9..aeee944 100755
--- a/lib/ipmi_dcmi.c
+++ b/lib/ipmi_dcmi.c
@@ -62,7 +62,7 @@
#define IPMI_LAN_PORT 0x26f
extern int verbose;
-
+extern int csv_output;
static int ipmi_print_sensor_info(struct ipmi_intf *intf, uint16_t rec_id);
/*******************************************************************************
@@ -295,6 +295,228 @@ const struct valstr dcmi_ccode_vals[] = {
{ 0xFF, NULL }
};
+/*
+ * Start of Node Manager Operations
+ */
+
+const struct dcmi_cmd dcmi_sampling_vals[] = {
+ { 0x05, "5_sec", "" },
+ { 0x0f, "15_sec", "" },
+ { 0x1E, "30_sec", "" },
+ { 0x41, "1_min", "" },
+ { 0x43, "3_min", "" },
+ { 0x47, "7_min", "" },
+ { 0x4F, "15_min", "" },
+ { 0x5E, "30_min", "" },
+ { 0x81, "1_hour", ""},
+ { 0x00, NULL, NULL },
+};
+
+/* Primary Node Manager commands */
+const struct dcmi_cmd nm_cmd_vals[] = {
+ { 0x00, "discover", "Discover Node Manager " },
+ { 0x01, "capability", "Get Node Manager Capabilities" },
+ { 0x02, "control", "Enable/Disable Policy Control" },
+ { 0x03, "policy", "Add/Remove Policies" },
+ { 0x04, "statistics", "Get Statistics" },
+ { 0x05, "power", "Set Power Draw Range" },
+ { 0x06, "suspend", "Set/Get Policy suspend periods" },
+ { 0x07, "reset", "Reset Statistics" },
+ { 0x08, "alert", "Set/Get/Clear Alert destination" },
+ { 0x09, "threshold", "Set/Get Alert Thresholds" },
+ { 0xFF, NULL, NULL },
+};
+
+const struct dcmi_cmd nm_ctl_cmds[] = {
+ { 0x01, "enable", " <control scope>" },
+ { 0x00, "disable", "<control scope>"},
+ { 0xFF, NULL, NULL },
+};
+
+const struct dcmi_cmd nm_ctl_domain[] = {
+ { 0x00, "global", "" },
+ { 0x02, "per_domain", "<platform|CPU|Memory> (default is platform)" },
+ { 0x04, "per_policy", "<0-7>" },
+ { 0xFF, NULL, NULL },
+};
+
+/* Node Manager Domain codes */
+const struct dcmi_cmd nm_domain_vals[] = {
+ { 0x00, "platform", "" },
+ { 0x01, "CPU", "" },
+ { 0x02, "Memory", "" },
+ { 0x03, "protection", "" },
+ { 0x04, "I/O", "" },
+ { 0xFF, NULL, NULL },
+};
+
+const struct dcmi_cmd nm_version_vals[] = {
+ { 0x01, "1.0", "" },
+ { 0x02, "1.5", "" },
+ { 0x03, "2.0", "" },
+ { 0x04, "2.5", "" },
+ { 0x05, "3.0", "" },
+ { 0xFF, NULL, NULL },
+};
+
+const struct dcmi_cmd nm_capability_opts[] = {
+ { 0x01, "domain", "<platform|CPU|Memory> (default is platform)" },
+ { 0x02, "inlet", "Inlet temp trigger" },
+ { 0x03, "missing", "Missing Power reading trigger" },
+ { 0x04, "reset", "Time after Host reset trigger" },
+ { 0x05, "boot", "Boot time policy" },
+ { 0xFF, NULL, NULL },
+};
+
+const struct dcmi_cmd nm_policy_type_vals[] = {
+ { 0x00, "No trigger, use Power Limit", "" },
+ { 0x01, "Inlet temp trigger", "" },
+ { 0x02, "Missing Power reading trigger", "" },
+ { 0x03, "Time after Host reset trigger", "" },
+ { 0x04, "number of cores to disable at boot time", "" },
+ { 0xFF, NULL, NULL },
+};
+
+const struct dcmi_cmd nm_stats_opts[] = {
+ { 0x01, "domain", "<platform|CPU|Memory> (default is platform)" },
+ { 0x02, "policy_id", "<0-7>" },
+ { 0xFF, NULL, NULL },
+};
+
+const struct dcmi_cmd nm_stats_mode[] = {
+ { 0x01, "power", "global power" },
+ { 0x02, "temps", "inlet temperature" },
+ { 0x11, "policy_power", "per policy power" },
+ { 0x12, "policy_temps", "per policy inlet temp" },
+ { 0x13, "policy_throt", "per policy throttling stats" },
+ { 0x1B, "requests", "unhandled requests" },
+ { 0x1C, "response", "response time" },
+ { 0x1D, "cpu_throttling", "CPU throttling" },
+ { 0x1E, "mem_throttling", "memory throttling" },
+ { 0x1F, "comm_fail", "host communication failures" },
+ { 0xFF, NULL, NULL },
+};
+
+const struct dcmi_cmd nm_policy_action[] = {
+ { 0x00, "get", "nm policy get policy_id <0-7> [domain <platform|CPU|Memory>]" },
+ { 0x04, "add", "nm policy add policy_id <0-7> [domain <platform|CPU|Memory>] correction auto|soft|hard power <watts>|inlet <temp> trig_lim <param> stats <seconds> enable|disable" },
+ { 0x05, "remove", "nm policy remove policy_id <0-7> [domain <platform|CPU|Memory>]" },
+ { 0x06, "limiting", "nm policy limiting [domain <platform|CPU|Memory>]" },
+ { 0xFF, NULL, NULL },
+};
+const struct dcmi_cmd nm_policy_options[] = {
+ { 0x01, "enable", "" },
+ { 0x02, "disable", "" },
+ { 0x03, "domain", "" },
+ { 0x04, "inlet", "inlet air temp full limiting (SCRAM)"},
+ { 0x06, "correction", "auto, soft, hard" },
+ { 0x08, "power", "power limit in watts" },
+ { 0x09, "trig_lim", "time to send alert" },
+ { 0x0A, "stats", "moving window averaging time" },
+ { 0x0B, "policy_id", "policy number" },
+ { 0x0C, "volatile", "save policy in volatiel memory" },
+ { 0x0D, "cores_off", "at boot time, disable N cores" },
+ { 0xFF, NULL, NULL },
+};
+
+/* if "trigger" command used from nm_policy_options */
+const struct dcmi_cmd nm_trigger[] = {
+ { 0x00, "none", "" },
+ { 0x01, "temp", "" },
+ { 0x02, "reset", "" },
+ { 0x03, "boot", "" },
+ { 0xFF, NULL, NULL },
+};
+
+/* if "correction" used from nm_policy_options */
+const struct dcmi_cmd nm_correction[] = {
+ { 0x00, "auto", "" },
+ { 0x01, "soft", "" },
+ { 0x02, "hard", "" },
+ { 0xFF, NULL, NULL },
+};
+
+/* returned codes from get policy */
+const struct dcmi_cmd nm_correction_vals[] = {
+ { 0x00, "no T-state use", "" },
+ { 0x01, "no T-state use", "" },
+ { 0x02, "use T-states", "" },
+ { 0xFF, NULL, NULL },
+};
+
+/* if "exception" used from nm_policy_options */
+const struct dcmi_cmd nm_exception[] = {
+ { 0x00, "none", "" },
+ { 0x01, "alert", "" },
+ { 0x02, "shutdown", "" },
+ { 0xFF, NULL, NULL },
+};
+
+const struct dcmi_cmd nm_reset_mode[] = {
+ { 0x00, "global", "" },
+ { 0x01, "per_policy", "" },
+ { 0x1B, "requests", "" },
+ { 0x1C, "response", "" },
+ { 0x1D, "throttling", "" },
+ { 0x1E, "memory", "", },
+ { 0x1F, "comm", "" },
+ { 0xFF, NULL, NULL },
+};
+
+const struct dcmi_cmd nm_power_range[] = {
+ { 0x01, "domain", "domain <platform|CPU|Memory> (default is platform)" },
+ { 0x02, "min", " min <integer value>" },
+ { 0x03, "max", "max <integer value>" },
+ { 0xFF, NULL, NULL },
+};
+
+const struct dcmi_cmd nm_alert_opts[] = {
+ { 0x01, "set", "nm alert set chan <chan> dest <dest> string <string>" },
+ { 0x02, "get", "nm alert get" },
+ { 0x03, "clear", "nm alert clear dest <dest>" },
+};
+
+const struct dcmi_cmd nm_set_alert_param[] = {
+ { 0x01, "chan", "chan <channel>" },
+ { 0x02, "dest", "dest <destination>" },
+ { 0x03, "string", "string <string>" },
+};
+
+const struct dcmi_cmd nm_thresh_cmds[] = {
+ { 0x01, "set", "nm thresh set [domain <platform|CPU|Memory>] policy_id <policy> thresh_array" },
+ { 0x02, "get", "nm thresh get [domain <platform|CPU|Memory>] policy_id <policy>" },
+};
+
+const struct dcmi_cmd nm_thresh_param[] = {
+ { 0x01, "domain", "<platform|CPU|Memory> (default is platform)" },
+ { 0x02, "policy_id", "<0-7>" },
+ { 0xFF, NULL, NULL },
+};
+
+const struct dcmi_cmd nm_suspend_cmds[] = {
+ { 0x01, "set", "nm suspend set [domain <platform|CPU|Memory]> policy_id <policy> <start> <stop> <pattern>" },
+ { 0x02, "get", "nm suspend get [domain <platform|CPU|Memory]> policy_id <policy>" },
+};
+
+const struct valstr nm_ccode_vals[] = {
+ { 0x80, "Policy ID Invalid"},
+ { 0x81, "Domain ID Invalid"},
+ { 0x82, "Unknown policy trigger type"},
+ { 0x84, "Power Limit out of range"},
+ { 0x85, "Correction Time out of range"},
+ { 0x86, "Policy Trigger value out of range"},
+ { 0x88, "Invalid Mode"},
+ { 0x89, "Statistics Reporting Period out of range"},
+ { 0x8B, "Invalid value for Aggressive CPU correction field"},
+ { 0xA1, "No policy is currently limiting for the specified domain ID"},
+ { 0xC4, "No space available"},
+ { 0xD4, "Insufficient privledge level due wrong responder LUN"},
+ { 0xD5, "Policy exists and param unchangeable while enabled"},
+ { 0xD6, "Command subfunction disabled or unavailable"},
+ { 0xFF, NULL },
+};
+
+
/* End strings */
/* This was taken from print_valstr() from helper.c. It serves the same
@@ -400,7 +622,7 @@ val2str2(uint16_t val, const struct dcmi_cmd *vs)
if (vs[i].val == val)
return vs[i].str;
}
- memset(un_str, 0, 32);
+ memset(un_str, 0, sizeof (un_str));
snprintf(un_str, 32, "Unknown (0x%x)", val);
return un_str;
}
@@ -439,6 +661,40 @@ chk_rsp(struct ipmi_rs * rsp)
return 0;
}
+/* check the Node Manager response from the BMC
+ * @rsp: Response data structure
+ */
+static int
+chk_nm_rsp(struct ipmi_rs * rsp)
+{
+ /* if the response from the intf is NULL then the BMC is experiencing
+ * some issue and cannot complete the command
+ */
+ if (rsp == NULL) {
+ lprintf(LOG_ERR, "\n No reponse to NM request");
+ return 1;
+ }
+ /* if the completion code is greater than zero there was an error. We'll
+ * use val2str from helper.c to print the error from either the DCMI
+ * completion code struct or the generic IPMI completion_code_vals struct
+ */
+ if ((rsp->ccode >= 0x80) && (rsp->ccode <= 0xD6)) {
+ lprintf(LOG_ERR, "\n NM request failed because: %s (%x)",
+ val2str(rsp->ccode, nm_ccode_vals), rsp->ccode);
+ return 1;
+ } else if (rsp->ccode > 0) {
+ lprintf(LOG_ERR, "\n NM request failed because: %s (%x)",
+ val2str(rsp->ccode, completion_code_vals), rsp->ccode);
+ return 1;
+ }
+ /* check to make sure this is a DCMI firmware */
+ if(rsp->data[0] != 0x57) {
+ printf("\n A valid NM command was not returned! (%x)", rsp->data[0]);
+ return 1;
+ }
+ return 0;
+}
+
/* Get capabilities ipmi response
*
* This function returns the available capabilities of the platform.
@@ -494,8 +750,7 @@ ipmi_dcmi_prnt_oobDiscover(struct ipmi_intf * intf)
"DCMI Discovery is available only when LANplus(IPMI v2.0) is enabled.");
return (-1);
# else
- int rc;
- struct ipmi_session *s;
+ struct ipmi_session_params *p;
if (intf->opened == 0 && intf->open != NULL) {
if (intf->open(intf) < 0)
@@ -504,18 +759,18 @@ ipmi_dcmi_prnt_oobDiscover(struct ipmi_intf * intf)
if (intf == NULL || intf->session == NULL)
return -1;
- s = intf->session;
+ p = &intf->ssn_params;
- if (s->port == 0)
- s->port = IPMI_LAN_PORT;
- if (s->privlvl == 0)
- s->privlvl = IPMI_SESSION_PRIV_ADMIN;
- if (s->timeout == 0)
- s->timeout = IPMI_LAN_TIMEOUT;
- if (s->retry == 0)
- s->retry = IPMI_LAN_RETRY;
+ if (p->port == 0)
+ p->port = IPMI_LAN_PORT;
+ if (p->privlvl == 0)
+ p->privlvl = IPMI_SESSION_PRIV_ADMIN;
+ if (p->timeout == 0)
+ p->timeout = IPMI_LAN_TIMEOUT;
+ if (p->retry == 0)
+ p->retry = IPMI_LAN_RETRY;
- if (s->hostname == NULL || strlen((const char *)s->hostname) == 0) {
+ if (p->hostname == NULL || strlen((const char *)p->hostname) == 0) {
lprintf(LOG_ERR, "No hostname specified!");
return -1;
}
@@ -530,7 +785,7 @@ ipmi_dcmi_prnt_oobDiscover(struct ipmi_intf * intf)
if (intf->fd < 0) {
lperror(LOG_ERR, "Connect to %s failed",
- s->hostname);
+ p->hostname);
intf->close(intf);
return -1;
}
@@ -552,17 +807,18 @@ ipmi_dcmi_prnt_oobDiscover(struct ipmi_intf * intf)
static int
ipmi_dcmi_prnt_getcapabilities(struct ipmi_intf * intf, uint8_t selector)
{
- uint8_t i;
- uint8_t bit_shifter = 0;
struct capabilities cape;
struct ipmi_rs * rsp;
+ uint8_t reply[16];
rsp = ipmi_dcmi_getcapabilities(intf, selector);
+ int j;
if(chk_rsp(rsp))
return -1;
/* if there were no errors, the command worked! */
memcpy(&cape, rsp->data, sizeof (cape));
+ memcpy(&reply, rsp->data, sizeof (reply));
/* check to make sure that this is a 1.0/1.1/1.5 command */
if ((cape.conformance != IPMI_DCMI_CONFORM)
&& (cape.conformance != IPMI_DCMI_1_1_CONFORM)
@@ -680,6 +936,16 @@ ipmi_dcmi_prnt_getcapabilities(struct ipmi_intf * intf, uint8_t selector)
cape.data_byte3);
}
break;
+ case 0x05:
+ /* Node Manager */
+ printf("\n Node Manager Get DCMI Capability Info: \n");
+ printf(" DCMI Specification %d.%d\n", reply[1], reply[2]);
+ printf(" Rolling average time period options: %d\n", reply[4]);
+ printf(" Sample time options: ");
+ for (j = 1; dcmi_sampling_vals[j-1].str != NULL; j++)
+ printf(" %s ", val2str2(reply[4+j],dcmi_sampling_vals));
+ printf("\n");
+ break;
default:
return -1;
}
@@ -728,7 +994,6 @@ ipmi_dcmi_getassettag(struct ipmi_intf * intf, uint8_t offset, uint8_t length)
static int
ipmi_dcmi_prnt_getassettag(struct ipmi_intf * intf)
{
- uint8_t data_byte2;
struct ipmi_rs * rsp; /* ipmi response */
uint8_t taglength = 0;
uint8_t getlength = 0;
@@ -800,16 +1065,15 @@ ipmi_dcmi_setassettag(struct ipmi_intf * intf, uint8_t offset, uint8_t length,
static int
ipmi_dcmi_prnt_setassettag(struct ipmi_intf * intf, uint8_t * data)
{
- uint8_t data_byte2;
struct ipmi_rs * rsp; /* ipmi response */
uint8_t tmpData[DCMI_MAX_BYTE_SIZE];
- uint8_t taglength = 0;
+ int32_t taglength = 0;
uint8_t getlength = 0;
uint8_t offset = 0;
uint8_t i;
/* now let's get the asset tag length */
- taglength = strlen(data);
+ taglength = strlen((char *)data);
if (taglength > 64){
lprintf(LOG_ERR, "\nValue is too long.");
return -1;
@@ -864,7 +1128,6 @@ ipmi_dcmi_getmngctrlids(struct ipmi_intf * intf, uint8_t offset, uint8_t length)
static int
ipmi_dcmi_prnt_getmngctrlids(struct ipmi_intf * intf)
{
- uint8_t data_byte2;
struct ipmi_rs * rsp; /* ipmi response */
uint8_t taglength = 0;
uint8_t getlength = 0;
@@ -942,7 +1205,6 @@ ipmi_dcmi_setmngctrlids(struct ipmi_intf * intf, uint8_t offset, uint8_t length,
static int
ipmi_dcmi_prnt_setmngctrlids(struct ipmi_intf * intf, uint8_t * data)
{
- uint8_t data_byte2;
struct ipmi_rs * rsp; /* ipmi response */
uint8_t tmpData[DCMI_MAX_BYTE_SIZE];
uint8_t taglength = 0;
@@ -951,7 +1213,7 @@ ipmi_dcmi_prnt_setmngctrlids(struct ipmi_intf * intf, uint8_t * data)
uint8_t i;
data += '\0';
- taglength = strlen(data) +1;
+ taglength = strlen((char *)data) +1;
if (taglength > 64) {
lprintf(LOG_ERR, "\nValue is too long.");
@@ -1048,7 +1310,7 @@ ipmi_dcmi_prnt_discvry_snsr(struct ipmi_intf * intf, uint8_t isnsr)
/* cache the data since it may be destroyed by subsequent
* ipmi_xxx calls
*/
- memcpy(id_buff, &rsp->data[3], 16);
+ memcpy(id_buff, &rsp->data[3], sizeof (id_buff));
for (i=0; i<records; i++) {
/* Record ID is in little endian format */
record_id = (id_buff[2*i + 1] << 8) + id_buff[2*i];
@@ -1067,7 +1329,7 @@ ipmi_dcmi_prnt_discvry_snsr(struct ipmi_intf * intf, uint8_t isnsr)
* @intf: ipmi interface handler
*/
static int
-ipmi_dcmi_pwr_rd(struct ipmi_intf * intf)
+ipmi_dcmi_pwr_rd(struct ipmi_intf * intf, uint8_t sample_time)
{
struct ipmi_rs * rsp;
struct ipmi_rq req;
@@ -1079,8 +1341,13 @@ ipmi_dcmi_pwr_rd(struct ipmi_intf * intf)
memset(&t, 0, sizeof(t));
msg_data[0] = IPMI_DCMI; /* Group Extension Identification */
- msg_data[1] = 0x01; /* Mode Power Status */
- msg_data[2] = 0x00; /* reserved */
+ if (sample_time) {
+ msg_data[1] = 0x02; /* Enhanced Power Statistics */
+ msg_data[2] = sample_time;
+ } else {
+ msg_data[1] = 0x01; /* Mode Power Status */
+ msg_data[2] = 0x00; /* reserved */
+ }
msg_data[3] = 0x00; /* reserved */
memset(&req, 0, sizeof(req));
@@ -1110,8 +1377,11 @@ ipmi_dcmi_pwr_rd(struct ipmi_intf * intf)
val.avg_pwr);
printf(" IPMI timestamp: %s",
asctime(&tm_t));
- printf(" Sampling period: %08d Milliseconds\n",
- val.sample);
+ printf(" Sampling period: ");
+ if (sample_time)
+ printf("%s \n", val2str2(val.sample,dcmi_sampling_vals));
+ else
+ printf("%08u Seconds.\n", val.sample/1000);
printf(" Power reading state is: ");
/* mask the rsp->data so that we only care about bit 6 */
if((val.state & 0x40) == 0x40) {
@@ -1496,7 +1766,6 @@ ipmi_dcmi_pwr_slimit(struct ipmi_intf * intf, const char * option,
struct power_limit val;
uint8_t msg_data[15]; /* number of request data bytes */
uint32_t lvalue = 0;
- int i;
rsp = ipmi_dcmi_pwr_glimit(intf); /* get the power limit settings */
# if 0
@@ -1674,7 +1943,7 @@ ipmi_dcmi_pwr_slimit(struct ipmi_intf * intf, const char * option,
*/
msg_data[11] = 0x00; /* reserved */
msg_data[12] = 0x00; /* reserved */
- /* fill msg_data[7] with the first 16 bits of val.sample */
+ /* fill msg_data[13] with the first 16 bits of val.sample */
*(uint16_t*)(&msg_data[13]) = val.sample;
/* msg_data[13] = 0x03; */
memset(&req, 0, sizeof(req));
@@ -1731,6 +2000,1578 @@ ipmi_dcmi_pwr_actdeact(struct ipmi_intf * intf, uint8_t option)
}
/* end power management activate/deactivate */
+/* Node Manager discover */
+static int
+_ipmi_nm_discover(struct ipmi_intf * intf, struct nm_discover *disc)
+{
+ struct ipmi_rq req; /* request data to send to the BMC */
+ struct ipmi_rs *rsp;
+ uint8_t msg_data[3]; /* 'raw' data to be sent to the BMC */
+
+ msg_data[0] = 0x57;
+ msg_data[1] = 1;
+ msg_data[2] = 0;
+ memset(&req, 0, sizeof(req));
+ req.msg.netfn = IPMI_NETFN_OEM;
+ req.msg.cmd = IPMI_NM_GET_VERSION;
+ req.msg.data = msg_data;
+ req.msg.data_len = 3;
+ rsp = intf->sendrecv(intf, &req);
+ if (chk_nm_rsp(rsp)) {
+ return -1;
+ }
+ memcpy(disc, rsp->data, sizeof (struct nm_discover));
+ return 0;
+}
+/* Get NM capabilities
+ *
+ * This function returns the available capabilities of the platform.
+ *
+ * returns success/failure
+ *
+ * @intf: ipmi interface handler
+ * @caps: fills in capability struct
+ */
+static int
+_ipmi_nm_getcapabilities(struct ipmi_intf * intf, uint8_t domain, uint8_t trigger, struct nm_capability *caps)
+{
+ struct ipmi_rq req; /* request data to send to the BMC */
+ struct ipmi_rs *rsp;
+ uint8_t msg_data[5]; /* 'raw' data to be sent to the BMC */
+
+ msg_data[0] = 0x57;
+ msg_data[1] = 1;
+ msg_data[2] = 0;
+ msg_data[3] = domain;
+ msg_data[4] = trigger; /* power control policy or trigger */
+ memset(&req, 0, sizeof(req));
+ req.msg.netfn = IPMI_NETFN_OEM;
+ req.msg.cmd = IPMI_NM_GET_CAP;
+ req.msg.data = msg_data;
+ req.msg.data_len = 5;
+ rsp = intf->sendrecv(intf, &req);
+ if (chk_nm_rsp(rsp)) {
+ return -1;
+ }
+ memcpy(caps, rsp->data, sizeof (struct nm_capability));
+ return 0;
+}
+
+static int
+_ipmi_nm_get_policy(struct ipmi_intf * intf, uint8_t domain, uint8_t policy_id, struct nm_get_policy *policy)
+{
+ struct ipmi_rq req; /* request data to send to the BMC */
+ struct ipmi_rs *rsp;
+ uint8_t msg_data[5]; /* 'raw' data to be sent to the BMC */
+
+ msg_data[0] = 0x57;
+ msg_data[1] = 1;
+ msg_data[2] = 0;
+ msg_data[3] = domain;
+ msg_data[4] = policy_id;
+ memset(&req, 0, sizeof(req));
+ req.msg.netfn = IPMI_NETFN_OEM;
+ req.msg.cmd = IPMI_NM_GET_POLICY;
+ req.msg.data = msg_data;
+ req.msg.data_len = 5;
+ rsp = intf->sendrecv(intf, &req);
+ if (chk_nm_rsp(rsp)) {
+ return -1;
+ }
+ memcpy(policy, rsp->data, sizeof (struct nm_get_policy));
+ return 0;
+}
+static int
+_ipmi_nm_set_policy(struct ipmi_intf * intf, struct nm_policy *policy)
+{
+ struct ipmi_rq req; /* request data to send to the BMC */
+ struct ipmi_rs *rsp;
+
+ memset(&req, 0, sizeof(req));
+ req.msg.netfn = IPMI_NETFN_OEM;
+ req.msg.cmd = IPMI_NM_SET_POLICY;
+ req.msg.data = (uint8_t *)policy;
+ req.msg.data_len = sizeof(struct nm_policy);
+ policy->intel_id[0] = 0x57; policy->intel_id[1] =1; policy->intel_id[2] =0;
+ rsp = intf->sendrecv(intf, &req);
+ if (chk_nm_rsp(rsp)) {
+ return -1;
+ }
+ return 0;
+}
+
+static int
+_ipmi_nm_policy_limiting(struct ipmi_intf * intf, uint8_t domain)
+{
+ struct ipmi_rq req; /* request data to send to the BMC */
+ struct ipmi_rs *rsp;
+ uint8_t msg_data[4]; /* 'raw' data to be sent to the BMC */
+
+ memset(&req, 0, sizeof(req));
+ req.msg.netfn = IPMI_NETFN_OEM;
+ req.msg.cmd = IPMI_NM_LIMITING;
+ msg_data[0] = 0x57;
+ msg_data[1] = 1;
+ msg_data[2] = 0;
+ msg_data[3] = domain;
+ req.msg.data = msg_data;
+ req.msg.data_len = 4;
+ rsp = intf->sendrecv(intf, &req);
+ /* check for special case error of no policy is limiting */
+ if (rsp && (rsp->ccode == 0xA1))
+ return 0x80;
+ else if (chk_nm_rsp(rsp))
+ return -1;
+ return rsp->data[0];
+}
+
+static int
+_ipmi_nm_control(struct ipmi_intf * intf, uint8_t scope, uint8_t domain, uint8_t policy_id)
+{
+ struct ipmi_rq req; /* request data to send to the BMC */
+ struct ipmi_rs *rsp;
+ uint8_t msg_data[6]; /* 'raw' data to be sent to the BMC */
+
+ msg_data[0] = 0x57;
+ msg_data[1] = 1;
+ msg_data[2] = 0;
+ msg_data[3] = scope;
+ msg_data[4] = domain;
+ msg_data[5] = policy_id;
+ memset(&req, 0, sizeof(req));
+ req.msg.netfn = IPMI_NETFN_OEM;
+ req.msg.cmd = IPMI_NM_POLICY_CTL;
+ req.msg.data = msg_data;
+ req.msg.data_len = 6;
+ rsp = intf->sendrecv(intf, &req);
+ if (chk_nm_rsp(rsp)) {
+ return -1;
+ }
+ return 0;
+}
+
+/* Get NM statistics
+ *
+ * This function returns the statistics
+ *
+ * returns success/failure
+ *
+ * @intf: ipmi interface handler
+ * @selector: Parameter selector
+ */
+static int
+_ipmi_nm_statistics(struct ipmi_intf * intf, uint8_t mode, uint8_t domain, uint8_t policy_id, struct nm_statistics *caps)
+{
+ struct ipmi_rq req; /* request data to send to the BMC */
+ struct ipmi_rs *rsp;
+ uint8_t msg_data[6]; /* 'raw' data to be sent to the BMC */
+
+ msg_data[0] = 0x57;
+ msg_data[1] = 1;
+ msg_data[2] = 0;
+ msg_data[3] = mode;
+ msg_data[4] = domain;
+ msg_data[5] = policy_id;
+ memset(&req, 0, sizeof(req));
+ req.msg.netfn = IPMI_NETFN_OEM;
+ req.msg.cmd = IPMI_NM_GET_STATS;
+ req.msg.data = msg_data;
+ req.msg.data_len = 6;
+ rsp = intf->sendrecv(intf, &req);
+ if (chk_nm_rsp(rsp)) {
+ return -1;
+ }
+ memcpy(caps, rsp->data, sizeof (struct nm_statistics));
+ return 0;
+}
+
+static int
+_ipmi_nm_reset_stats(struct ipmi_intf * intf, uint8_t mode, uint8_t domain, uint8_t policy_id)
+{
+ struct ipmi_rq req; /* request data to send to the BMC */
+ struct ipmi_rs *rsp;
+ uint8_t msg_data[6]; /* 'raw' data to be sent to the BMC */
+
+ msg_data[0] = 0x57;
+ msg_data[1] = 1;
+ msg_data[2] = 0;
+ msg_data[3] = mode;
+ msg_data[4] = domain;
+ msg_data[5] = policy_id;
+ memset(&req, 0, sizeof(req));
+ req.msg.netfn = IPMI_NETFN_OEM;
+ req.msg.cmd = IPMI_NM_RESET_STATS;
+ req.msg.data = msg_data;
+ req.msg.data_len = 6;
+ rsp = intf->sendrecv(intf, &req);
+ if (chk_nm_rsp(rsp)) {
+ return -1;
+ }
+ return 0;
+}
+
+static int
+_nm_set_range(struct ipmi_intf * intf, uint8_t domain, uint16_t minimum, uint16_t maximum)
+{
+ struct ipmi_rq req; /* request data to send to the BMC */
+ struct ipmi_rs *rsp;
+ uint8_t msg_data[8]; /* 'raw' data to be sent to the BMC */
+
+ msg_data[0] = 0x57;
+ msg_data[1] = 1;
+ msg_data[2] = 0;
+ msg_data[3] = domain;
+ msg_data[4] = minimum & 0xFF;
+ msg_data[5] = minimum >> 8;
+ msg_data[6] = maximum & 0xFF;
+ msg_data[7] = maximum >> 8;
+ memset(&req, 0, sizeof(req));
+ req.msg.netfn = IPMI_NETFN_OEM;
+ req.msg.cmd = IPMI_NM_SET_POWER;
+ req.msg.data = msg_data;
+ req.msg.data_len = 8;
+ rsp = intf->sendrecv(intf, &req);
+ if (chk_nm_rsp(rsp)) {
+ return -1;
+ }
+ return 0;
+}
+
+static int
+_ipmi_nm_get_alert(struct ipmi_intf * intf, struct nm_set_alert *alert)
+{
+ struct ipmi_rq req; /* request data to send to the BMC */
+ struct ipmi_rs *rsp;
+ uint8_t msg_data[3]; /* 'raw' data to be sent to the BMC */
+
+ msg_data[0] = 0x57;
+ msg_data[1] = 1;
+ msg_data[2] = 0;
+ memset(&req, 0, sizeof(req));
+ req.msg.netfn = IPMI_NETFN_OEM;
+ req.msg.cmd = IPMI_NM_GET_ALERT_DS;
+ req.msg.data = msg_data;
+ req.msg.data_len = 3;
+ rsp = intf->sendrecv(intf, &req);
+ if (chk_nm_rsp(rsp)) {
+ return -1;
+ }
+ memcpy(alert, rsp->data, sizeof (struct nm_set_alert));
+ return 0;
+}
+
+static int
+_ipmi_nm_set_alert(struct ipmi_intf * intf, struct nm_set_alert *alert)
+{
+ struct ipmi_rq req; /* request data to send to the BMC */
+ struct ipmi_rs *rsp;
+ uint8_t msg_data[6]; /* 'raw' data to be sent to the BMC */
+
+ msg_data[0] = 0x57;
+ msg_data[1] = 1;
+ msg_data[2] = 0;
+ msg_data[3] = alert->chan;
+ msg_data[4] = alert->dest;
+ msg_data[5] = alert->string;
+ memset(&req, 0, sizeof(req));
+ req.msg.netfn = IPMI_NETFN_OEM;
+ req.msg.cmd = IPMI_NM_SET_ALERT_DS;
+ req.msg.data = msg_data;
+ req.msg.data_len = 6;
+ rsp = intf->sendrecv(intf, &req);
+ if (chk_nm_rsp(rsp)) {
+ return -1;
+ }
+ return 0;
+}
+
+/*
+ *
+ * get alert threshold values.
+ *
+ * the list pointer is assumed to point to an array of 16 short integers.
+ * This array is filled in for valid thresholds returned.
+ */
+static int
+_ipmi_nm_get_thresh(struct ipmi_intf * intf, uint8_t domain, uint8_t policy_id, uint16_t *list)
+{
+ struct ipmi_rq req; /* request data to send to the BMC */
+ struct ipmi_rs *rsp;
+ uint8_t msg_data[5]; /* 'raw' data to be sent to the BMC */
+
+ msg_data[0] = 0x57;
+ msg_data[1] = 1;
+ msg_data[2] = 0;
+ msg_data[3] = domain;
+ msg_data[4] = policy_id;
+ memset(&req, 0, sizeof(req));
+ req.msg.netfn = IPMI_NETFN_OEM;
+ req.msg.cmd = IPMI_NM_GET_ALERT_TH;
+ req.msg.data = msg_data;
+ req.msg.data_len = 5;
+ rsp = intf->sendrecv(intf, &req);
+ if (chk_nm_rsp(rsp)) {
+ return -1;
+ }
+ if (rsp->data[3] > 0)
+ *list++ = (rsp->data[5] << 8) | rsp->data[4];
+ if (rsp->data[3] > 1)
+ *list++ = (rsp->data[7] << 8) | rsp->data[6];
+ if (rsp->data[3] > 2)
+ *list = (rsp->data[9] << 8) | rsp->data[8];
+ return 0;
+}
+
+static int
+_ipmi_nm_set_thresh(struct ipmi_intf * intf, struct nm_thresh * thresh)
+{
+ struct ipmi_rq req; /* request data to send to the BMC */
+ struct ipmi_rs *rsp;
+ uint8_t msg_data[IPMI_NM_SET_THRESH_LEN]; /* 'raw' data to be sent to the BMC */
+
+ memset(&msg_data, 0, sizeof(msg_data));
+ msg_data[0] = 0x57;
+ msg_data[1] = 1;
+ msg_data[2] = 0;
+ msg_data[3] = thresh->domain;
+ msg_data[4] = thresh->policy_id;
+ msg_data[5] = thresh->count;
+ if (thresh->count > 0) {
+ msg_data[7] = thresh->thresholds[0] >> 8;
+ msg_data[6] = thresh->thresholds[0] & 0xFF;
+ }
+ if (thresh->count > 1) {
+ msg_data[9] = thresh->thresholds[1] >> 8;
+ msg_data[8] = thresh->thresholds[1] & 0xFF;
+ }
+ if (thresh->count > 2) {
+ msg_data[11] = thresh->thresholds[2] >> 8;
+ msg_data[10] = thresh->thresholds[2] & 0xFF;
+ }
+ memset(&req, 0, sizeof(req));
+ req.msg.netfn = IPMI_NETFN_OEM;
+ req.msg.cmd = IPMI_NM_SET_ALERT_TH;
+ req.msg.data = msg_data;
+ req.msg.data_len = 6 + (thresh->count * 2);
+ rsp = intf->sendrecv(intf, &req);
+ if (chk_nm_rsp(rsp)) {
+ return -1;
+ }
+ return 0;
+}
+
+/*
+ *
+ * get suspend periods
+ *
+ */
+static int
+_ipmi_nm_get_suspend(struct ipmi_intf * intf, uint8_t domain, uint8_t policy_id, int *count, struct nm_period *periods)
+{
+ struct ipmi_rq req; /* request data to send to the BMC */
+ struct ipmi_rs *rsp;
+ uint8_t msg_data[5]; /* 'raw' data to be sent to the BMC */
+ int i;
+
+ msg_data[0] = 0x57;
+ msg_data[1] = 1;
+ msg_data[2] = 0;
+ msg_data[3] = domain;
+ msg_data[4] = policy_id;
+ memset(&req, 0, sizeof(req));
+ req.msg.netfn = IPMI_NETFN_OEM;
+ req.msg.cmd = IPMI_NM_GET_SUSPEND;
+ req.msg.data = msg_data;
+ req.msg.data_len = 5;
+ rsp = intf->sendrecv(intf, &req);
+ if (chk_nm_rsp(rsp)) {
+ return -1;
+ }
+ *count = rsp->data[3];
+ for (i = 0; i < rsp->data[3]; i += 3, periods++) {
+ periods->start = rsp->data[4+i];
+ periods->stop = rsp->data[5+i];
+ periods->repeat = rsp->data[6+i];
+ }
+ return 0;
+}
+
+static int
+_ipmi_nm_set_suspend(struct ipmi_intf * intf, struct nm_suspend *suspend)
+{
+ struct ipmi_rq req; /* request data to send to the BMC */
+ struct ipmi_rs *rsp;
+ uint8_t msg_data[21]; /* 6 control bytes + 5 suspend periods, 3 bytes per period */
+ struct nm_period *periods;
+ int i;
+
+ msg_data[0] = 0x57;
+ msg_data[1] = 1;
+ msg_data[2] = 0;
+ msg_data[3] = suspend->domain;
+ msg_data[4] = suspend->policy_id;
+ msg_data[5] = suspend->count;
+ for (i = 0, periods = &suspend->period[0]; i < (suspend->count*3); i += 3, periods++) {
+ msg_data[6+i] = periods->start;
+ msg_data[7+i] = periods->stop;
+ msg_data[8+i] = periods->repeat;
+ }
+ memset(&req, 0, sizeof(req));
+ req.msg.data_len = 6 + (suspend->count*3);
+ req.msg.netfn = IPMI_NETFN_OEM;
+ req.msg.cmd = IPMI_NM_SET_SUSPEND;
+ req.msg.data = msg_data;
+ rsp = intf->sendrecv(intf, &req);
+ if (chk_nm_rsp(rsp)) {
+ return -1;
+ }
+ return 0;
+}
+
+static int
+ipmi_nm_getcapabilities(struct ipmi_intf * intf, int argc, char **argv)
+{
+ uint8_t option;
+ uint8_t domain = 0; /* default domain of platform */
+ uint8_t trigger = 0; /* default power policy (no trigger) */
+ struct nm_capability caps;
+
+ while (--argc > 0) {
+ argv++;
+ if (argv[0] == NULL) break;
+ if ((option = str2val2(argv[0], nm_capability_opts)) == 0xFF) {
+ print_strs(nm_capability_opts, "Capability commands", LOG_ERR, 0);
+ return -1;
+ }
+ switch (option) {
+ case 0x01: /* get domain scope */
+ if ((domain = str2val2(argv[1], nm_domain_vals)) == 0xFF) {
+ print_strs(nm_domain_vals, "Domain Scope:", LOG_ERR, 0);
+ return -1;
+ }
+ break;
+ case 0x02: /* Inlet */
+ trigger = 1;
+ break;
+ case 0x03: /* Missing power reading */
+ trigger = 2;
+ break;
+ case 0x04: /* Time after host reset */
+ trigger = 3;
+ break;
+ case 0x05: /* Boot time policy */
+ trigger = 4;
+ break;
+ default:
+ break;
+ }
+ argc--;
+ argv++;
+ }
+ trigger |= 0x10;
+ memset(&caps, 0, sizeof(caps));
+ if (_ipmi_nm_getcapabilities(intf, domain, trigger, &caps))
+ return -1;
+ if (csv_output) {
+ printf("%d,%u,%u,%u,%u,%u,%u,%s\n",
+ caps.max_settings, caps.max_value,caps.min_value,
+ caps.min_corr/1000, caps.max_corr/1000,
+ caps.min_stats, caps.max_stats,
+ val2str2(caps.scope&0xF, nm_domain_vals));
+ return 0;
+ }
+ printf(" power policies:\t\t%d\n", caps.max_settings);
+ switch (trigger&0xF) {
+ case 0: /* power */
+ printf(" max_power\t\t%7u Watts\n min_power\t\t%7u Watts\n",
+ caps.max_value, caps.min_value);
+ break;
+ case 1: /* Inlet */
+ printf(" max_temp\t\t%7u C\n min_temp\t\t%7u C\n",
+ caps.max_value, caps.min_value);
+ break;
+ case 2: /* Missing reading time */
+ case 3: /* Time after host reset */
+ printf(" max_time\t\t%7u Secs\n min_time\t\t%7u Secs\n",
+ caps.max_value/10, caps.min_value/10);
+ break;
+ case 4: /* boot time policy does not use these values */
+ default:
+ break;
+ }
+ printf(" min_corr\t\t%7u secs\n max_corr\t\t%7u secs\n",
+ caps.min_corr/1000, caps.max_corr/1000);
+ printf(" min_stats\t\t%7u secs\n max_stats\t\t%7u secs\n",
+ caps.min_stats, caps.max_stats);
+ printf(" domain scope:\t%s\n", val2str2(caps.scope&0xF, nm_domain_vals));
+ return 0;
+}
+
+static int
+ipmi_nm_get_policy(struct ipmi_intf * intf, int argc, char **argv)
+{
+ uint8_t option;
+ uint8_t domain = 0; /* default domain of platform */
+ uint8_t policy_id = -1;
+ struct nm_get_policy policy;
+
+ memset(&policy, 0, sizeof(policy));
+
+ while (--argc) {
+ argv++;
+ if (argv[0] == NULL) break;
+ if ((option = str2val2(argv[0], nm_policy_options)) == 0xFF) {
+ print_strs(nm_policy_options, "Get Policy commands", LOG_ERR, 0);
+ return -1;
+ }
+ switch (option) {
+ case 0x03: /* get domain scope */
+ if ((domain = str2val2(argv[1], nm_domain_vals)) == 0xFF) {
+ print_strs(nm_domain_vals, "Domain Scope:", LOG_ERR, 0);
+ return -1;
+ }
+ policy.domain |= domain & 0xF;
+ break;
+ case 0x0B: /* policy id */
+ if (str2uchar(argv[1], &policy_id) < 0) {
+ lprintf(LOG_ERR," Policy ID must be a positive integer 0-7.\n");
+ return -1;
+ }
+ break;
+ default:
+ printf(" Unknown command 0x%x, skipping.\n", option);
+ break;
+ }
+ argc--;
+ argv++;
+ }
+ if (policy_id == 0xFF) {
+ print_strs(nm_stats_opts, "Missing policy_id parameter:", LOG_ERR, 0);
+ return -1;
+ }
+ if (_ipmi_nm_get_policy(intf, policy.domain, policy_id, &policy))
+ return -1;
+ if (csv_output) {
+ printf("%s,0x%x,%s,%s,%s,%u,%u,%u,%u,%s\n",
+ val2str2(policy.domain&0xF, nm_domain_vals),
+ policy.domain,
+ (policy.policy_type & 0x10) ? "power" : "nopower ",
+ val2str2(policy.policy_type & 0xF, nm_policy_type_vals),
+ val2str2(policy.policy_exception, nm_exception),
+ policy.policy_limits,
+ policy.corr_time,
+ policy.trigger_limit,
+ policy.stats_period,
+ policy.policy_type & 0x80 ? "volatile" : "non-volatile");
+ return 0;
+ }
+ printf(" Power domain: %s\n",
+ val2str2(policy.domain&0xF, nm_domain_vals));
+ printf(" Policy is %s %s%s%s\n",
+ policy.domain&0x10 ? "enabled" : "not enabled",
+ policy.domain&0x20 ? "per Domain " : "",
+ policy.domain&0x40 ? "Globally " : "",
+ policy.domain&0x80 ? "via DCMI api " : "");
+ printf(" Policy is %sa power control type.\n", (policy.policy_type & 0x10) ? "" : "not ");
+ printf(" Policy Trigger Type: %s\n",
+ val2str2(policy.policy_type & 0xF, nm_policy_type_vals));
+ printf(" Correction Aggressiveness: %s\n",
+ val2str2((policy.policy_type>> 5) & 0x3, nm_correction_vals));
+ printf(" Policy Exception Actions: %s\n",
+ val2str2(policy.policy_exception, nm_exception));
+ printf(" Power Limit: %u Watts\n",
+ policy.policy_limits);
+ printf(" Correction Time Limit: %u milliseconds\n",
+ policy.corr_time);
+ printf(" Trigger Limit: %u units\n",
+ policy.trigger_limit);
+ printf(" Statistics Reporting Period: %u seconds\n",
+ policy.stats_period);
+ printf(" Policy retention: %s\n",
+ policy.policy_type & 0x80 ? "volatile" : "non-volatile");
+ if ( (policy_id == 0) && ((policy.domain & 0xf) == 0x3) )
+ printf(" HW Prot Power domain: %s\n",
+ policy.policy_type & 0x80 ? "Secondary" : "Primary");
+ return 0;
+}
+
+static int
+ipmi_nm_policy(struct ipmi_intf * intf, int argc, char **argv)
+{
+ uint8_t action;
+ uint8_t option;
+ uint8_t correction;
+ uint8_t domain = 0; /* default domain of platform */
+ uint8_t policy_id = -1;
+ uint16_t power, period, inlet;
+ uint16_t cores;
+ uint32_t limit;
+ struct nm_policy policy;
+
+ argv++;
+ argc--;
+ if ((argv[0] == NULL) ||
+ ((action = str2val2(argv[0], nm_policy_action)) == 0xFF)) {
+ print_strs(nm_policy_action, "Policy commands", LOG_ERR, 0);
+ return -1;
+ }
+ if (action == 0) /* get */
+ return (ipmi_nm_get_policy(intf, argc, argv));
+ memset(&policy, 0, sizeof(policy));
+ /*
+ * nm policy add [domain <param>] enable|disable policy_id <param> correction <opt> power <watts> limit <param> period <param>
+ * nm policy remove [domain <param>] policy_id <param>
+ * nm policy limiting {domain <param>]
+ */
+ while (--argc > 0) {
+ argv++;
+ if (argv[0] == NULL) break;
+ if ((option = str2val2(argv[0], nm_policy_options)) == 0xFF) {
+ print_strs(nm_policy_options, "Policy options", LOG_ERR, 0);
+ return -1;
+ }
+ switch (option) {
+ case 0x01: /* policy enable */
+ policy.domain |= IPMI_NM_POLICY_ENABLE;
+ break;
+ case 0x02: /* policy disable */
+ break; /* value is initialized to zero already */
+ case 0x03: /* get domain scope */
+ if ((domain = str2val2(argv[1], nm_domain_vals)) == 0xFF) {
+ print_strs(nm_domain_vals, "Domain Scope:", LOG_ERR, 0);
+ return -1;
+ }
+ policy.domain |= domain & 0xF;
+ break;
+ case 0x04: /* inlet */
+ if (str2ushort(argv[1], &inlet) < 0) {
+ printf("Inlet Temp value must be 20-45.\n");
+ return -1;
+ }
+ policy.policy_type |= 1;
+ policy.policy_limits = 0;
+ policy.trigger_limit = inlet;
+ break;
+ case 0x06: /* get correction action */
+ if (action == 0x5) break; /* skip if this is a remove */
+ if ((correction = str2val2(argv[1], nm_correction)) == 0xFF) {
+ print_strs(nm_correction, "Correction Actions", LOG_ERR, 0);
+ return -1;
+ }
+ policy.policy_type |= (correction << 5);
+ break;
+ case 0x07: /* not implemented */
+ break;
+ case 0x08: /* power */
+ if (str2ushort(argv[1], &power) < 0) {
+ printf("Power limit value must be 0-500.\n");
+ return -1;
+ }
+ policy.policy_limits = power;
+ break;
+ case 0x09: /* trigger limit */
+ if (str2uint(argv[1], &limit) < 0) {
+ printf("Trigger Limit value must be positive integer.\n");
+ return -1;
+ }
+ policy.corr_time = limit;
+ break;
+ case 0x0A: /* statistics period */
+ if (str2ushort(argv[1], &period) < 0) {
+ printf("Statistics Reporting Period must be positive integer.\n");
+ return -1;
+ }
+ policy.stats_period = period;
+ break;
+ case 0x0B: /* policy ID */
+ if (str2uchar(argv[1], &policy_id) < 0) {
+ printf("Policy ID must be a positive integer 0-7.\n");
+ return -1;
+ }
+ policy.policy_id = policy_id;
+ break;
+ case 0x0C: /* volatile */
+ policy.policy_type |= 0x80;
+ break;
+ case 0x0D: /* cores_off, number of cores to disable at boot time */
+ policy.policy_type |= 4;
+ if (str2ushort(argv[1], &cores) < 0) {
+ printf("number of cores disabled must be 1-127.\n");
+ return -1;
+ }
+ if ((cores < 1) || (cores > 127)) {
+ printf("number of cores disabled must be 1-127.\n");
+ return -1;
+ }
+ policy.policy_type |= 4;
+ policy.policy_limits = cores << 1;
+ break;
+ default:
+ break;
+ }
+ argc--;
+ argv++;
+ }
+ if (action == 0x06) { /* limiting */
+ if ((limit = _ipmi_nm_policy_limiting(intf, domain) == -1))
+ return -1;
+ printf("limit %x\n", limit);
+ return 0;
+ }
+ if (policy_id == 0xFF) {
+ print_strs(nm_stats_opts, "Missing policy_id parameter:", LOG_ERR, 0);
+ return -1;
+ }
+ if (action == 0x04) /* add */
+ policy.policy_type |= 0x10;
+ if (_ipmi_nm_set_policy(intf, &policy))
+ return -1;
+ return 0;
+}
+/* end policy */
+
+static int
+ipmi_nm_control(struct ipmi_intf * intf, int argc, char **argv)
+{
+ uint8_t action;
+ uint8_t scope = 0; /* default control scope of global */
+ uint8_t domain = 0; /* default domain of platform */
+ uint8_t policy_id = -1;
+
+ argv++;
+ argc--;
+ /* nm_ctl_cmds returns 0 for disable, 1 for enable */
+ if ((argv[0] == NULL) ||
+ ((action = str2val2(argv[0], nm_ctl_cmds)) == 0xFF)) {
+ print_strs(nm_ctl_cmds, "Control parameters:", LOG_ERR, 0);
+ print_strs(nm_ctl_domain, "control Scope (required):", LOG_ERR, 0);
+ return -1;
+ }
+ argv++;
+ while (--argc) {
+ /* nm_ctl_domain returns correct bit field except for action */
+ if ((argv[0] == NULL) ||
+ ((scope = str2val2(argv[0], nm_ctl_domain)) == 0xFF)) {
+ print_strs(nm_ctl_domain, "Control Scope (required):", LOG_ERR, 0);
+ return -1;
+ }
+ argv++;
+ if (argv[0] == NULL) break;
+ if (scope == 0x02) { /* domain */
+ if ((domain = str2val2(argv[0], nm_domain_vals)) == 0xFF) {
+ print_strs(nm_domain_vals, "Domain Scope:", LOG_ERR, 0);
+ return -1;
+ }
+ } else if (scope == 0x04) { /* per_policy */
+
+ if (str2uchar(argv[0], &policy_id) < 0) {
+ lprintf(LOG_ERR,"Policy ID must be a positive integer.\n");
+ return -1;
+ }
+ break;
+ }
+ argc--;
+ argv++;
+ }
+ if ((scope == 0x04) && (policy_id == 0xFF)) {
+ print_strs(nm_stats_opts, "Missing policy_id parameter:", LOG_ERR, 0);
+ return -1;
+ }
+ if (_ipmi_nm_control(intf, scope|(action&1), domain, policy_id) < 0 )
+ return -1;
+ return 0;
+}
+
+static int
+ipmi_nm_get_statistics(struct ipmi_intf * intf, int argc, char **argv)
+{
+ uint8_t mode = 0;
+ uint8_t option;
+ uint8_t domain = 0; /* default domain of platform */
+ uint8_t policy_id = -1;
+ int policy_mode = 0;
+ int cut;
+ char *units = "";
+ char datebuf[27];
+ struct nm_statistics stats;
+ struct tm tm_t;
+ time_t t;
+
+ argv++;
+ if ((argv[0] == NULL) ||
+ ((mode = str2val2(argv[0], nm_stats_mode)) == 0xFF)) {
+ print_strs(nm_stats_mode, "Statistics commands", LOG_ERR, 0);
+ return -1;
+ }
+ while (--argc) {
+ argv++;
+ if (argv[0] == NULL) break;
+ if ((option = str2val2(argv[0], nm_stats_opts)) == 0xFF) {
+ print_strs(nm_stats_opts, "Control Scope options", LOG_ERR, 0);
+ return -1;
+ }
+ switch (option) {
+ case 0x01: /* get domain scope */
+ if ((domain = str2val2(argv[1], nm_domain_vals)) == 0xFF) {
+ print_strs(nm_domain_vals, "Domain Scope:", LOG_ERR, 0);
+ return -1;
+ }
+ break;
+ case 0x02: /* policy ID */
+ if (str2uchar(argv[1], &policy_id) < 0) {
+ lprintf(LOG_ERR,"Policy ID must be a positive integer.\n");
+ return -1;
+ }
+ break;
+ default:
+ break;
+ }
+ argc--;
+ argv++;
+ }
+
+ switch (mode) {
+ case 0x01:
+ units = "Watts";
+ break;
+ case 0x02:
+ units = "Celsius";
+ break;
+ case 0x03:
+ units = "%";
+ break;
+ case 0x11:
+ case 0x12:
+ case 0x13:
+ policy_mode = 1;
+ units = (mode == 0x11) ? "Watts" : (mode == 0x12) ? "Celsius" : " %";
+ if (policy_id == 0xFF) {
+ print_strs(nm_stats_opts, "Missing policy_id parameter:", LOG_ERR, 0);
+ return -1;
+ }
+ break;
+ default:
+ break;
+ }
+ if (_ipmi_nm_statistics(intf, mode, domain, policy_id, &stats))
+ return -1;
+ t = stats.time_stamp;
+ gmtime_r(&t, &tm_t);
+ sprintf(datebuf, "%s", asctime(&tm_t));
+ cut = strlen(datebuf) -1;
+ datebuf[cut] = 0;
+ if (csv_output) {
+ printf("%s,%s,%s,%s,%s,%d,%d,%d,%d,%s,%d\n",
+ val2str2(stats.id_state & 0xF, nm_domain_vals),
+ ((stats.id_state >> 4) & 1) ? (policy_mode ? "Policy Enabled" : "Globally Enabled") : "Disabled" ,
+ ((stats.id_state >> 5) & 1) ? "active" : "suspended",
+ ((stats.id_state >> 6) & 1) ? "in progress" : "suspended",
+ ((stats.id_state >> 7) & 1) ? "triggered" : "not triggered",
+ stats.curr_value,
+ stats.min_value,
+ stats.max_value,
+ stats.ave_value,
+ datebuf,
+ stats.stat_period);
+ return 0;
+ }
+ printf(" Power domain: %s\n",
+ val2str2(stats.id_state & 0xF, nm_domain_vals));
+ printf(" Policy/Global Admin state %s\n",
+ ((stats.id_state >> 4) & 1) ? (policy_mode ? "Policy Enabled" : "Globally Enabled") : "Disabled" );
+ printf(" Policy/Global Operational state %s\n",
+ ((stats.id_state >> 5) & 1) ? "active" : "suspended");
+ printf(" Policy/Global Measurement state %s\n",
+ ((stats.id_state >> 6) & 1) ? "in progress" : "suspended");
+ printf(" Policy Activation state %s\n",
+ ((stats.id_state >> 7) & 1) ? "triggered" : "not triggered");
+ printf(" Instantaneous reading: %8d %s\n",
+ stats.curr_value, units);
+ printf(" Minimum during sampling period: %8d %s\n",
+ stats.min_value, units);
+ printf(" Maximum during sampling period: %8d %s\n",
+ stats.max_value, units);
+ printf(" Average reading over sample period: %8d %s\n",
+ stats.ave_value, units);
+ printf(" IPMI timestamp: %s\n",
+ datebuf);
+ printf(" Sampling period: %08d Seconds.\n", stats.stat_period);
+ printf("\n");
+ return 0;
+}
+
+static int
+ipmi_nm_reset_statistics(struct ipmi_intf * intf, int argc, char **argv)
+{
+ uint8_t mode;
+ uint8_t option;
+ uint8_t domain = 0; /* default domain of platform */
+ uint8_t policy_id = -1;
+
+ argv++;
+ if ((argv[0] == NULL) ||
+ ((mode = str2val2(argv[0], nm_reset_mode)) == 0xFF)) {
+ print_strs(nm_reset_mode, "Reset Statistics Modes:", LOG_ERR, 0);
+ return -1;
+ }
+ while (--argc) {
+ argv++;
+ if (argv[0] == NULL) break;
+ if ((option = str2val2(argv[0], nm_stats_opts)) == 0xFF) {
+ print_strs(nm_stats_opts, "Reset Scope options", LOG_ERR, 0);
+ return -1;
+ }
+ switch (option) {
+ case 0x01: /* get domain scope */
+ if ((domain = str2val2(argv[1], nm_domain_vals)) == 0xFF) {
+ print_strs(nm_domain_vals, "Domain Scope:", LOG_ERR, 0);
+ return -1;
+ }
+ break;
+ case 0x02: /* policy ID */
+ if (str2uchar(argv[1], &policy_id) < 0) {
+ lprintf(LOG_ERR,"Policy ID must be a positive integer.\n");
+ return -1;
+ }
+ break;
+ default:
+ break;
+ }
+ argc--;
+ argv++;
+ }
+ if (mode && (policy_id == 0xFF)) {
+ print_strs(nm_stats_opts, "Missing policy_id parameter:", LOG_ERR, 0);
+ return -1;
+ }
+ if (_ipmi_nm_reset_stats(intf, mode, domain, policy_id) < 0)
+ return -1;
+ return 0;
+}
+
+static int
+ipmi_nm_set_range(struct ipmi_intf * intf, int argc, char **argv)
+{
+ uint8_t domain = 0;
+ uint8_t param;
+ uint16_t minimum = -1;
+ uint16_t maximum = -1;
+
+ while (--argc) {
+ argv++;
+ if (argv[0] == NULL) break;
+ if ((param = str2val2(argv[0], nm_power_range)) == 0xFF) {
+ print_strs(nm_power_range, "power range parameters:", LOG_ERR, 0);
+ return -1;
+ }
+ switch (param) {
+ case 0x01: /* get domain scope */
+ if ((domain = str2val2(argv[1], nm_domain_vals)) == 0xFF) {
+ print_strs(nm_domain_vals, "Domain Scope:", LOG_ERR, 0);
+ return -1;
+ }
+ break;
+ case 0x02: /* min */
+ if (str2ushort(argv[1], &minimum) < 0) {
+ lprintf(LOG_ERR,"Power minimum must be a positive integer.\n");
+ return -1;
+ }
+ break;
+ case 0x03: /* max */
+ if (str2ushort(argv[1], &maximum) < 0) {
+ lprintf(LOG_ERR,"Power maximum must be a positive integer.\n");
+ return -1;
+ }
+ break;
+ default:
+ break;
+ }
+ argc--;
+ argv++;
+ }
+ if ((minimum == 0xFFFF) || (maximum == 0xFFFF)) {
+ lprintf(LOG_ERR,"Missing parameters: nm power range min <minimum> max <maximum>.\n");
+ return -1;
+ }
+ if (_nm_set_range(intf, domain, minimum, maximum) < 0)
+ return -1;
+ return 0;
+}
+
+static int
+ipmi_nm_get_alert(struct ipmi_intf * intf)
+{
+ struct nm_set_alert alert;
+
+ memset(&alert, 0, sizeof(alert));
+ if (_ipmi_nm_get_alert(intf, &alert))
+ return -1;
+ if (csv_output) {
+ printf("%d,%s,0x%x,%s,0x%x\n",
+ alert.chan&0xF,
+ (alert.chan >> 7) ? "not registered" : "registered",
+ alert.dest,
+ (alert.string >> 7) ? "yes" : "no",
+ alert.string & 0x7F);
+ return 0;
+ }
+ printf(" Alert Chan: %d\n",
+ alert.chan&0xF);
+ printf(" Alert Receiver: %s\n",
+ (alert.chan >> 7) ? "not registered" : "registered");
+ printf(" Alert Lan Destination: 0x%x\n",
+ alert.dest);
+ printf(" Use Alert String: %s\n",
+ (alert.string >> 7) ? "yes" : "no");
+ printf(" Alert String Selector: 0x%x\n",
+ alert.string & 0x7F);
+ return 0;
+}
+
+static int
+ipmi_nm_alert(struct ipmi_intf * intf, int argc, char **argv)
+{
+ uint8_t param;
+ uint8_t action;
+ uint8_t chan = -1;
+ uint8_t dest = -1;
+ uint8_t string = -1;
+ struct nm_set_alert alert;
+
+ argv++;
+ argc--;
+ if ((argv[0] == NULL) ||
+ ((action = str2val2(argv[0], nm_alert_opts)) == 0xFF)) {
+ print_strs(nm_alert_opts, "Alert commands", LOG_ERR, 0);
+ return -1;
+ }
+ if (action == 0x02) /* get */
+ return (ipmi_nm_get_alert(intf));
+ /* set */
+ memset(&alert, 0, sizeof(alert));
+ while (--argc) {
+ argv++;
+ if (argv[0] == NULL) break;
+ if ((param = str2val2(argv[0], nm_set_alert_param)) == 0xFF) {
+ print_strs(nm_set_alert_param, "Set alert Parameters:", LOG_ERR, 0);
+ return -1;
+ }
+ switch (param) {
+ case 0x01: /* channnel */
+ if (str2uchar(argv[1], &chan) < 0) {
+ lprintf(LOG_ERR,"Alert Lan chan must be a positive integer.\n");
+ return -1;
+ }
+ if (action == 0x03) /* Clear */
+ chan |= 0x80; /* deactivate alert reciever */
+ break;
+ case 0x02: /* dest */
+ if (str2uchar(argv[1], &dest) < 0) {
+ lprintf(LOG_ERR,"Alert Destination must be a positive integer.\n");
+ return -1;
+ }
+ break;
+ case 0x03: /* string number */
+ if (str2uchar(argv[1], &string) < 0) {
+ lprintf(LOG_ERR,"Alert String # must be a positive integer.\n");
+ return -1;
+ }
+ string |= 0x80; /* set string select flag */
+ break;
+ }
+ argc--;
+ argv++;
+ }
+ if ((chan == 0xFF) || (dest == 0xFF)) {
+ print_strs(nm_set_alert_param, "Must set alert chan and dest params.", LOG_ERR, 0);
+ return -1;
+ }
+ if (string == 0xFF) string = 0;
+ alert.chan = chan;
+ alert.dest = dest;
+ alert.string = string;
+ if (_ipmi_nm_set_alert(intf, &alert))
+ return -1;
+ return 0;
+}
+
+static int
+ipmi_nm_get_thresh(struct ipmi_intf *intf, uint8_t domain, uint8_t policy_id)
+{
+ uint16_t list[3];
+
+ memset(list, 0, sizeof(list));
+ if (_ipmi_nm_get_thresh(intf, domain, policy_id, &list[0]))
+ return -1;
+
+ printf(" Alert Threshold domain: %s\n",
+ val2str2(domain, nm_domain_vals));
+ printf(" Alert Threshold Policy ID: %d\n",
+ policy_id);
+ printf(" Alert Threshold 1: %d\n",
+ list[0]);
+ printf(" Alert Threshold 2: %d\n",
+ list[1]);
+ printf(" Alert Threshold 3: %d\n",
+ list[2]);
+ return 0;
+}
+
+static int
+ipmi_nm_thresh(struct ipmi_intf * intf, int argc, char **argv)
+{
+ uint8_t option;
+ uint8_t action;
+ uint8_t domain = 0; /* default domain of platform */
+ uint8_t policy_id = -1;
+ struct nm_thresh thresh;
+ int i = 0;
+
+ argv++;
+ argc--;
+ /* set or get */
+ if ((argv[0] == NULL) || (argc < 3) ||
+ ((action = str2val2(argv[0], nm_thresh_cmds)) == 0xFF)) {
+ print_strs(nm_thresh_cmds, "Theshold commands", LOG_ERR, 0);
+ return -1;
+ }
+ memset(&thresh, 0, sizeof(thresh));
+ while (--argc) {
+ argv++;
+ if (argv[0] == NULL) break;
+ option = str2val2(argv[0], nm_thresh_param);
+ switch (option) {
+ case 0x01: /* get domain scope */
+ if ((domain = str2val2(argv[1], nm_domain_vals)) == 0xFF) {
+ print_strs(nm_domain_vals, "Domain Scope:", LOG_ERR, 0);
+ return -1;
+ }
+ argc--;
+ argv++;
+ break;
+ case 0x02: /* policy ID */
+ if (str2uchar(argv[1], &policy_id) < 0) {
+ lprintf(LOG_ERR,"Policy ID must be a positive integer.\n");
+ return -1;
+ }
+ argc--;
+ argv++;
+ break;
+ case 0xFF:
+ if (i > 2) {
+ lprintf(LOG_ERR,"Set Threshold requires 1, 2, or 3 threshold integer values.\n");
+ return -1;
+ }
+ if (str2ushort(argv[0], &thresh.thresholds[i++]) < 0) {
+ lprintf(LOG_ERR,"threshold value %d count must be a positve integer.\n", i);
+ return -1;
+ }
+ default:
+ break;
+ }
+ }
+ if (policy_id == 0xFF) {
+ print_strs(nm_stats_opts, "Missing policy_id parameter:", LOG_ERR, 0);
+ return -1;
+ }
+ if (action == 0x02) /* get */
+ return (ipmi_nm_get_thresh(intf, domain, policy_id));
+ thresh.domain = domain;
+ thresh.policy_id = policy_id;
+ thresh.count = i;
+ if (_ipmi_nm_set_thresh(intf, &thresh) < 0)
+ return -1;
+ return 0;
+}
+
+static inline int
+click2hour(int click)
+{
+ if ((click*6) < 60) return 0;
+ return ((click*6)/60);
+}
+
+static inline int
+click2min(int click)
+{
+ if (!click) return 0;
+ if ((click*6) < 60) return click*6;
+ return (click*6)%60;
+}
+
+static int
+ipmi_nm_get_suspend(struct ipmi_intf *intf, uint8_t domain, uint8_t policy_id)
+{
+ struct nm_period periods[5];
+ int i;
+ int j;
+ int count = 0;
+ const char *days[7] = {"M", "Tu", "W", "Th", "F", "Sa", "Su"};
+
+ memset(periods, 0, sizeof(periods));
+ if (_ipmi_nm_get_suspend(intf, domain, policy_id, &count, &periods[0]))
+ return -1;
+
+ printf(" Suspend Policy domain: %s\n",
+ val2str2(domain, nm_domain_vals));
+ printf(" Suspend Policy Policy ID: %d\n",
+ policy_id);
+ if (!count) {
+ printf(" No suspend Periods.\n");
+ return 0;
+ }
+ for (i = 0; i < count; i++) {
+ printf(" Suspend Period %d: %02d:%02d to %02d:%02d",
+ i, click2hour(periods[i].start), click2min(periods[i].start),
+ click2hour(periods[i].stop), click2min(periods[i].stop));
+ if (periods[i].repeat) printf(", ");
+ for (j = 0; j < 7; j++)
+ printf("%s", (periods[i].repeat >> j)&1 ? days[j] : "");
+ printf("\n");
+ }
+ return 0;
+}
+
+static int
+ipmi_nm_suspend(struct ipmi_intf * intf, int argc, char **argv)
+{
+ uint8_t option;
+ uint8_t action;
+ uint8_t domain = 0; /* default domain of platform */
+ uint8_t policy_id = -1;
+ uint8_t count = 0;
+ struct nm_suspend suspend;
+ int i;
+
+ argv++;
+ argc--;
+ /* set or get */
+ if ((argv[0] == NULL) || (argc < 3) ||
+ ((action = str2val2(argv[0], nm_suspend_cmds)) == 0xFF)) {
+ print_strs(nm_suspend_cmds, "Suspend commands", LOG_ERR, 0);
+ return -1;
+ }
+ memset(&suspend, 0, sizeof(suspend));
+ while (--argc > 0) {
+ argv++;
+ if (argv[0] == NULL) break;
+ option = str2val2(argv[0], nm_thresh_param);
+ switch (option) {
+ case 0x01: /* get domain scope */
+ if ((domain = str2val2(argv[1], nm_domain_vals)) == 0xFF) {
+ print_strs(nm_domain_vals, "Domain Scope:", LOG_ERR, 0);
+ return -1;
+ }
+ argc--;
+ argv++;
+ break;
+ case 0x02: /* policy ID */
+ if (str2uchar(argv[1], &policy_id) < 0) {
+ lprintf(LOG_ERR,"Policy ID must be a positive integer.\n");
+ return -1;
+ }
+ argc--;
+ argv++;
+ break;
+ case 0xFF: /* process periods */
+ for (i = 0; count < IPMI_NM_SUSPEND_PERIOD_MAX; i += 3, count++) {
+ if (argc < 3) {
+ lprintf(LOG_ERR,"Error: suspend period requires a start, stop, and repeat values.\n");
+ return -1;
+ }
+ if (str2uchar(argv[i+0], &suspend.period[count].start) < 0) {
+ lprintf(LOG_ERR,"suspend start value %d must be 0-239.\n", count);
+ return -1;
+ }
+ if (str2uchar(argv[i+1], &suspend.period[count].stop) < 0) {
+ lprintf(LOG_ERR,"suspend stop value %d must be 0-239.\n", count);
+ return -1;
+ }
+ if (str2uchar(argv[i+2], &suspend.period[count].repeat) < 0) {
+ lprintf(LOG_ERR,"suspend repeat value %d unable to convert.\n", count);
+ return -1;
+ }
+ argc -= 3;
+ if (argc <= 0)
+ break;
+ }
+ if (argc <= 0)
+ break;
+ break;
+ default:
+ break;
+ }
+ }
+ if (action == 0x02) /* get */
+ return (ipmi_nm_get_suspend(intf, domain, policy_id));
+
+ suspend.domain = domain;
+ suspend.policy_id = policy_id;
+ if (_ipmi_nm_set_suspend(intf, &suspend) < 0)
+ return -1;
+ return 0;
+}
+/* end nm */
+
+static int
+ipmi_dcmi_set_limit(struct ipmi_intf * intf, int argc, char **argv)
+{
+ int rc = 0;
+
+ if ( argc == 10) {
+ /* Let`s initialize dcmi power parameters */
+ struct ipmi_rq req;
+ uint8_t data[256];
+ uint16_t sample = 0;
+ uint16_t limit = 0;
+ uint32_t correction = 0;
+ struct ipmi_rs *rsp;
+
+ memset(data, 0, sizeof(data));
+ memset(&req, 0, sizeof(req));
+
+ req.msg.netfn = IPMI_NETFN_DCGRP;
+ req.msg.lun = 0x00;
+ req.msg.cmd = IPMI_DCMI_SETLMT; /* Set power limit */
+ req.msg.data = data; /* Contents above */
+ req.msg.data_len = 15;
+
+ data[0] = IPMI_DCMI; /* Group Extension Identification */
+ data[1] = 0x0; /* reserved */
+ data[2] = 0x0; /* reserved */
+ data[3] = 0x0; /* reserved */
+
+ /* action */
+ switch (str2val2(argv[2], dcmi_pwrmgmt_action_vals)) {
+ case 0x00:
+ /* no_action */
+ data[4] = 0x00;
+ break;
+ case 0x01:
+ /* power_off */
+ data[4] = 0x01;
+ break;
+ case 0x11:
+ /* sel_logging*/
+ data[4] = 0x11;
+ break;
+ case 0xFF:
+ /* error - not a string we knew what to do with */
+ lprintf(LOG_ERR, "Given Action '%s' is invalid.",
+ argv[2]);
+ return -1;
+ }
+ /* limit */
+ if (str2ushort(argv[4], &limit) != 0) {
+ lprintf(LOG_ERR,
+ "Given Limit '%s' is invalid.",
+ argv[4]);
+ return (-1);
+ }
+ data[5] = limit >> 0;
+ data[6] = limit >> 8;
+ /* correction */
+ if (str2uint(argv[6], &correction) != 0) {
+ lprintf(LOG_ERR,
+ "Given Correction '%s' is invalid.",
+ argv[6]);
+ return (-1);
+ }
+ data[7] = correction >> 0;
+ data[8] = correction >> 8;
+ data[9] = correction >> 16;
+ data[10] = correction >> 24;
+ data[11] = 0x00; /* reserved */
+ data[12] = 0x00; /* reserved */
+ /* sample */
+ if (str2ushort(argv[8], &sample) != 0) {
+ lprintf(LOG_ERR,
+ "Given Sample '%s' is invalid.",
+ argv[8]);
+ return (-1);
+ }
+ data[13] = sample >> 0;
+ data[14] = sample >> 8;
+
+ rsp = intf->sendrecv(intf, &req);
+ if (chk_rsp(rsp)) {
+ return -1;
+ }
+ } else {
+ /* loop through each parameter and value until we have neither */
+ while ((argv[1] != NULL) && (argv[2] != NULL)) {
+ rc = ipmi_dcmi_pwr_slimit(intf, argv[1], argv[2]);
+ /* catch any error that the set limit function returned */
+ if (rc > 0) {
+ print_strs(dcmi_pwrmgmt_set_usage_vals,
+ "set_limit <parameter> <value>", LOG_ERR, 0);
+ return -1;
+ }
+ /* the first argument is the command and the second is the
+ * value. Move argv two places; what is now 3 will be 1
+ */
+ argv+=2;
+ }
+ }
+ return rc;
+}
+
+static int
+ipmi_dcmi_parse_power(struct ipmi_intf * intf, int argc, char **argv)
+{
+ int rc = 0;
+ uint8_t sample_time = 0;
+ /* power management */
+ switch (str2val2(argv[0], dcmi_pwrmgmt_vals)) {
+ case 0x00:
+ /* get reading */
+ if (argv[1] != NULL) {
+ if (!(sample_time = str2val2(argv[1], dcmi_sampling_vals))) {
+ print_strs(dcmi_sampling_vals,
+ "Invalid sample time. Valid times are: ",
+ LOG_ERR, 1);
+ printf("\n");
+ return -1;
+ }
+ }
+ rc = ipmi_dcmi_pwr_rd(intf, sample_time);
+ break;
+ case 0x01:
+ /* get limit */
+ /* because the get limit function is also used to
+ * populate unchanged values for the set limit
+ * command it returns an ipmi response structure
+ */
+ rc = ipmi_dcmi_pwr_prnt_glimit(intf);
+ break;
+ case 0x02:
+ /* set limit */
+ if (argc < 4) {
+ print_strs(dcmi_pwrmgmt_set_usage_vals,
+ "set_limit <parameter> <value>",
+ LOG_ERR, 0);
+ return -1;
+ }
+ if (ipmi_dcmi_set_limit(intf, argc, argv) < 0)
+ return -1;
+ rc = ipmi_dcmi_pwr_prnt_glimit(intf);
+ break;
+ case 0x03:
+ /* activate */
+ rc = ipmi_dcmi_pwr_actdeact(intf, 1);
+ break;
+ case 0x04:
+ /* deactivate */
+ rc = ipmi_dcmi_pwr_actdeact(intf, 0);
+ break;
+ default:
+ /* no valid options */
+ print_strs(dcmi_pwrmgmt_vals,
+ "power <command>", LOG_ERR, 0);
+ break;
+ }
+ return rc;
+}
+/* end dcmi power command */
+
+static int
+ipmi_dcmi_thermalpolicy(struct ipmi_intf * intf, int argc, char **argv)
+{
+ int rc = 0;
+ uint8_t entityID = 0;
+ uint8_t entityInst = 0;
+ uint8_t persistanceFlag;
+ uint8_t actionHardPowerOff;
+ uint8_t actionLogToSEL;
+ uint8_t tempLimit = 0;
+ uint8_t samplingTimeLSB;
+ uint8_t samplingTimeMSB;
+ uint16_t samplingTime = 0;
+ /* Thermal policy get/set */
+ /* dcmitool dcmi thermalpolicy get */
+ switch (str2val2(argv[1], dcmi_thermalpolicy_vals)) {
+ case 0x00:
+ if (argc < 4) {
+ lprintf(LOG_NOTICE, "Get <entityID> <instanceID>");
+ return -1;
+ }
+ if (str2uchar(argv[2], &entityID) != 0) {
+ lprintf(LOG_ERR,
+ "Given Entity ID '%s' is invalid.",
+ argv[2]);
+ return (-1);
+ }
+ if (str2uchar(argv[3], &entityInst) != 0) {
+ lprintf(LOG_ERR,
+ "Given Instance ID '%s' is invalid.",
+ argv[3]);
+ return (-1);
+ }
+ rc = ipmi_dcmi_getthermalpolicy(intf, entityID, entityInst);
+ break;
+ case 0x01:
+ if (argc < 4) {
+ lprintf(LOG_NOTICE, "Set <entityID> <instanceID>");
+ return -1;
+ } else if (argc < 9) {
+ print_strs(dcmi_thermalpolicy_set_parameters_vals,
+ "Set thermalpolicy instance parameters: "
+ "<volatile/nonvolatile/disabled> "
+ "<poweroff/nopoweroff/disabled> "
+ "<sel/nosel/disabled> <templimitByte> <exceptionTime>",
+ LOG_ERR, 0);
+ return -1;
+ }
+ if (str2uchar(argv[2], &entityID) != 0) {
+ lprintf(LOG_ERR,
+ "Given Entity ID '%s' is invalid.",
+ argv[2]);
+ return (-1);
+ }
+ if (str2uchar(argv[3], &entityInst) != 0) {
+ lprintf(LOG_ERR,
+ "Given Instance ID '%s' is invalid.",
+ argv[3]);
+ return (-1);
+ }
+ persistanceFlag = (uint8_t) str2val2(argv[4], dcmi_thermalpolicy_set_parameters_vals);
+ actionHardPowerOff = (uint8_t) str2val2(argv[5], dcmi_thermalpolicy_set_parameters_vals);
+ actionLogToSEL = (uint8_t) str2val2(argv[6], dcmi_thermalpolicy_set_parameters_vals);
+ if (str2uchar(argv[7], &tempLimit) != 0) {
+ lprintf(LOG_ERR,
+ "Given Temp Limit '%s' is invalid.",
+ argv[7]);
+ return (-1);
+ }
+ if (str2ushort(argv[8], &samplingTime) != 0) {
+ lprintf(LOG_ERR,
+ "Given Sampling Time '%s' is invalid.",
+ argv[8]);
+ return (-1);
+ }
+ samplingTimeLSB = (samplingTime & 0xFF);
+ samplingTimeMSB = ((samplingTime & 0xFF00) >> 8);
+
+ rc = ipmi_dcmi_setthermalpolicy(intf,
+ entityID,
+ entityInst,
+ persistanceFlag,
+ actionHardPowerOff,
+ actionLogToSEL,
+ tempLimit,
+ samplingTimeLSB,
+ samplingTimeMSB);
+
+ break;
+ default:
+ print_strs(dcmi_thermalpolicy_vals,
+ "thermalpolicy <command>",
+ LOG_ERR, 0);
+ return -1;
+ }
+ return rc;
+}
+
/* main
*
* @intf: dcmi interface handler
@@ -1741,14 +3582,13 @@ int
ipmi_dcmi_main(struct ipmi_intf * intf, int argc, char **argv)
{
int rc = 0;
- uint8_t ctl = 0;
- int i, ii, instances;
+ int i;
struct ipmi_rs *rsp;
if ((argc == 0) || (strncmp(argv[0], "help", 4) == 0)) {
print_strs(dcmi_cmd_vals,
"Data Center Management Interface commands",
- -1, 0);
+ LOG_ERR, 0);
return -1;
}
/* start the cmd requested */
@@ -1757,7 +3597,7 @@ ipmi_dcmi_main(struct ipmi_intf * intf, int argc, char **argv)
/* discover capabilities*/
for (i = 1; dcmi_capable_vals[i-1].str != NULL; i++) {
if (ipmi_dcmi_prnt_getcapabilities(intf, i) < 0) {
- printf("Error discovering %s capabilities!\n",
+ lprintf(LOG_ERR,"Error discovering %s capabilities!\n",
val2str2(i, dcmi_capable_vals));
return -1;
}
@@ -1768,142 +3608,10 @@ ipmi_dcmi_main(struct ipmi_intf * intf, int argc, char **argv)
argv++;
if (argv[0] == NULL) {
print_strs(dcmi_pwrmgmt_vals, "power <command>",
- -1, 0);
+ LOG_ERR, 0);
return -1;
}
- /* power management */
- switch (str2val2(argv[0], dcmi_pwrmgmt_vals)) {
- case 0x00:
- /* get reading */
- rc = ipmi_dcmi_pwr_rd(intf);
- break;
- case 0x01:
- /* get limit */
- /* because the get limit function is also used to
- * populate unchanged values for the set limit
- * command it returns an ipmi response structure
- */
- rc = ipmi_dcmi_pwr_prnt_glimit(intf);
- break;
- case 0x02:
- /* set limit */
- if (argc < 4) {
- print_strs(dcmi_pwrmgmt_set_usage_vals,
- "set_limit <parameter> <value>",
- -1, 0);
- return -1;
- }
- if ( argc == 10) {
- /* Let`s initialize dcmi power parameters */
- struct ipmi_rq req;
- uint8_t data[256];
- uint16_t sample = 0;
- uint16_t limit = 0;
- uint32_t correction = 0;
-
- memset(data, 0, sizeof(data));
- memset(&req, 0, sizeof(req));
-
- req.msg.netfn = IPMI_NETFN_DCGRP;
- req.msg.lun = 0x00;
- req.msg.cmd = IPMI_DCMI_SETLMT; /* Set power limit */
- req.msg.data = data; /* Contents above */
- req.msg.data_len = 15;
-
- data[0] = IPMI_DCMI; /* Group Extension Identification */
- data[1] = 0x0; /* reserved */
- data[2] = 0x0; /* reserved */
- data[3] = 0x0; /* reserved */
-
- /* action */
- switch (str2val2(argv[2], dcmi_pwrmgmt_action_vals)) {
- case 0x00:
- /* no_action */
- data[4] = 0x00;
- break;
- case 0x01:
- /* power_off */
- data[4] = 0x01;
- break;
- case 0x11:
- /* sel_logging*/
- data[4] = 0x11;
- break;
- case 0xFF:
- /* error - not a string we knew what to do with */
- lprintf(LOG_ERR, "Given Action '%s' is invalid.",
- argv[2]);
- return -1;
- }
- /* limit */
- if (str2ushort(argv[4], &limit) != 0) {
- lprintf(LOG_ERR,
- "Given Limit '%s' is invalid.",
- argv[4]);
- return (-1);
- }
- data[5] = limit >> 0;
- data[6] = limit >> 8;
- /* correction */
- if (str2uint(argv[6], &correction) != 0) {
- lprintf(LOG_ERR,
- "Given Correction '%s' is invalid.",
- argv[6]);
- return (-1);
- }
- data[7] = correction >> 0;
- data[8] = correction >> 8;
- data[9] = correction >> 16;
- data[10] = correction >> 24;
- data[11] = 0x00; /* reserved */
- data[12] = 0x00; /* reserved */
- /* sample */
- if (str2ushort(argv[8], &sample) != 0) {
- lprintf(LOG_ERR,
- "Given Sample '%s' is invalid.",
- argv[8]);
- return (-1);
- }
- data[13] = sample >> 0;
- data[14] = sample >> 8;
-
- rsp = intf->sendrecv(intf, &req);
- if (chk_rsp(rsp)) {
- return -1;
- }
- } else {
- /* loop through each parameter and value until we have neither */
- while ((argv[1] != NULL) && (argv[2] != NULL)) {
- rc = ipmi_dcmi_pwr_slimit(intf, argv[1], argv[2]);
- /* catch any error that the set limit function returned */
- if (rc > 0) {
- print_strs(dcmi_pwrmgmt_set_usage_vals,
- "set_limit <parameter> <value>", -1, 0);
- return -1;
- }
- /* the first argument is the command and the second is the
- * value. Move argv two places; what is now 3 will be 1
- */
- argv+=2;
- }
- }
- rc = ipmi_dcmi_pwr_prnt_glimit(intf);
- break;
- case 0x03:
- /* activate */
- rc = ipmi_dcmi_pwr_actdeact(intf, 1);
- break;
- case 0x04:
- /* deactivate */
- rc = ipmi_dcmi_pwr_actdeact(intf, 0);
- break;
- default:
- /* no valid options */
- print_strs(dcmi_pwrmgmt_vals,
- "power <command>", -1, 0);
- break;
- }
- /* power mgmt end */
+ rc = ipmi_dcmi_parse_power(intf, argc, argv);
break;
/* end power command */
case 0x02:
@@ -1933,10 +3641,10 @@ ipmi_dcmi_main(struct ipmi_intf * intf, int argc, char **argv)
if (argc == 1 ) {
print_strs(dcmi_cmd_vals,
"Data Center Management Interface commands",
- -1, 0);
+ LOG_ERR, 0);
return -1;
}
- if (ipmi_dcmi_prnt_setassettag(intf, argv[1]) < 0) {
+ if (ipmi_dcmi_prnt_setassettag(intf, (uint8_t *)argv[1]) < 0) {
lprintf(LOG_ERR, "\nError setting asset tag!");
return -1;
}
@@ -1958,10 +3666,10 @@ ipmi_dcmi_main(struct ipmi_intf * intf, int argc, char **argv)
if (argc == 1 ) {
print_strs(dcmi_cmd_vals,
"Data Center Management Interface commands",
- -1, 0);
+ LOG_ERR, 0);
return -1;
}
- if (ipmi_dcmi_prnt_setmngctrlids(intf, argv[1]) < 0) {
+ if (ipmi_dcmi_prnt_setmngctrlids(intf, (uint8_t *)argv[1]) < 0) {
lprintf(LOG_ERR,
"Error setting management controller identifier string!");
return -1;
@@ -1970,110 +3678,21 @@ ipmi_dcmi_main(struct ipmi_intf * intf, int argc, char **argv)
}
/* end set management controller identifier string */
case 0x07:
- {
- uint8_t entityID = 0;
- uint8_t entityInst = 0;
- uint8_t persistanceFlag;
- uint8_t actionHardPowerOff;
- uint8_t actionLogToSEL;
- uint8_t tempLimit = 0;
- uint8_t samplingTimeLSB;
- uint8_t samplingTimeMSB;
- uint16_t samplingTime = 0;
- /* Thermal policy get/set */
- /* dcmitool dcmi thermalpolicy get */
- switch (str2val2(argv[1], dcmi_thermalpolicy_vals)) {
- case 0x00:
- if (argc < 4) {
- lprintf(LOG_NOTICE, "Get <entityID> <instanceID>");
- return -1;
- }
- if (str2uchar(argv[2], &entityID) != 0) {
- lprintf(LOG_ERR,
- "Given Entity ID '%s' is invalid.",
- argv[2]);
- return (-1);
- }
- if (str2uchar(argv[3], &entityInst) != 0) {
- lprintf(LOG_ERR,
- "Given Instance ID '%s' is invalid.",
- argv[3]);
- return (-1);
- }
- rc = ipmi_dcmi_getthermalpolicy(intf, entityID, entityInst);
- break;
- case 0x01:
- if (argc < 4) {
- lprintf(LOG_NOTICE, "Set <entityID> <instanceID>");
- return -1;
- } else if (argc < 9) {
- print_strs(dcmi_thermalpolicy_set_parameters_vals,
- "Set thermalpolicy instance parameters: "
- "<volatile/nonvolatile/disabled> "
- "<poweroff/nopoweroff/disabled> "
- "<sel/nosel/disabled> <templimitByte> <exceptionTime>",
- -1, 0);
- return -1;
- }
- if (str2uchar(argv[2], &entityID) != 0) {
- lprintf(LOG_ERR,
- "Given Entity ID '%s' is invalid.",
- argv[2]);
- return (-1);
- }
- if (str2uchar(argv[3], &entityInst) != 0) {
- lprintf(LOG_ERR,
- "Given Instance ID '%s' is invalid.",
- argv[3]);
- return (-1);
- }
- persistanceFlag = (uint8_t) str2val2(argv[4], dcmi_thermalpolicy_set_parameters_vals);
- actionHardPowerOff = (uint8_t) str2val2(argv[5], dcmi_thermalpolicy_set_parameters_vals);
- actionLogToSEL = (uint8_t) str2val2(argv[6], dcmi_thermalpolicy_set_parameters_vals);
- if (str2uchar(argv[7], &tempLimit) != 0) {
- lprintf(LOG_ERR,
- "Given Temp Limit '%s' is invalid.",
- argv[7]);
- return (-1);
- }
- if (str2ushort(argv[8], &samplingTime) != 0) {
- lprintf(LOG_ERR,
- "Given Sampling Time '%s' is invalid.",
- argv[8]);
- return (-1);
- }
- samplingTimeLSB = (samplingTime & 0xFF);
- samplingTimeMSB = ((samplingTime & 0xFF00) >> 8);
-
- rc = ipmi_dcmi_setthermalpolicy(intf,
- entityID,
- entityInst,
- persistanceFlag,
- actionHardPowerOff,
- actionLogToSEL,
- tempLimit,
- samplingTimeLSB,
- samplingTimeMSB);
-
- break;
- default:
- print_strs(dcmi_thermalpolicy_vals,
- "thermalpolicy <command>",
- -1, 0);
- return -1;
- }
+ /* get/set thermal policy */
+ rc = ipmi_dcmi_thermalpolicy(intf, argc, argv);
break;
- }
case 0x08:
if(ipmi_dcmi_prnt_get_temp_readings(intf) < 0 ) {
lprintf(LOG_ERR,
"Error get temperature readings!");
+ return -1;
}
break;
case 0x09:
if(ipmi_dcmi_prnt_getconfparam(intf) < 0 ) {
lprintf(LOG_ERR,
"Error Get DCMI Configuration Parameters!");
+ return -1;
};
break;
case 0x0A:
@@ -2083,7 +3702,7 @@ ipmi_dcmi_main(struct ipmi_intf * intf, int argc, char **argv)
if (strncmp(argv[1], "activate_dhcp", 13) != 0) {
print_strs( dcmi_conf_param_vals,
"DCMI Configuration Parameters",
- -1, 0);
+ LOG_ERR, 0);
return -1;
}
break;
@@ -2091,7 +3710,7 @@ ipmi_dcmi_main(struct ipmi_intf * intf, int argc, char **argv)
if (argc != 3 || strncmp(argv[1], "help", 4) == 0) {
print_strs(dcmi_conf_param_vals,
"DCMI Configuration Parameters",
- -1, 0);
+ LOG_ERR, 0);
return -1;
}
}
@@ -2132,11 +3751,90 @@ ipmi_dcmi_main(struct ipmi_intf * intf, int argc, char **argv)
/* couldn't detect what the user entered */
print_strs(dcmi_cmd_vals,
"Data Center Management Interface commands",
- -1, 0);
+ LOG_ERR, 0);
return -1;
break;
}
printf("\n");
+ return rc;
+}
+
+/* Node Manager main
+ *
+ * @intf: nm interface handler
+ * @argc: argument count
+ * @argv: argument vector
+ */
+int
+ipmi_nm_main(struct ipmi_intf * intf, int argc, char **argv)
+{
+ struct nm_discover disc;
+
+ if ((argc == 0) || (strncmp(argv[0], "help", 4) == 0)) {
+ print_strs(nm_cmd_vals,
+ "Node Manager Interface commands",
+ LOG_ERR, 0);
+ return -1;
+ }
+
+ switch (str2val2(argv[0], nm_cmd_vals)) {
+ /* discover */
+ case 0x00:
+ if (_ipmi_nm_discover(intf, &disc))
+ return -1;
+ printf(" Node Manager Version %s\n", val2str2(disc.nm_version, nm_version_vals));
+ printf(" revision %d.%d%d patch version %d\n", disc.major_rev,
+ disc.minor_rev>>4, disc.minor_rev&0xf, disc.patch_version);
+ break;
+ /* capability */
+ case 0x01:
+ if (ipmi_nm_getcapabilities(intf, argc, argv))
+ return -1;
+ break;
+ /* policy control enable-disable */
+ case 0x02:
+ if (ipmi_nm_control(intf, argc, argv))
+ return -1;
+ break;
+ /* policy */
+ case 0x03:
+ if (ipmi_nm_policy(intf, argc, argv))
+ return -1;
+ break;
+ /* Get statistics */
+ case 0x04:
+ if (ipmi_nm_get_statistics(intf, argc, argv))
+ return -1;
+ break;
+ /* set power draw range */
+ case 0x05:
+ if (ipmi_nm_set_range(intf, argc, argv))
+ return -1;
+ break;
+ /* set/get suspend periods */
+ case 0x06:
+ if (ipmi_nm_suspend(intf, argc, argv))
+ return -1;
+ break;
+ /* reset statistics */
+ case 0x07:
+ if (ipmi_nm_reset_statistics(intf, argc, argv))
+ return -1;
+ break;
+ /* set/get alert destination */
+ case 0x08:
+ if (ipmi_nm_alert(intf, argc, argv))
+ return -1;
+ break;
+ /* set/get alert thresholds */
+ case 0x09:
+ if (ipmi_nm_thresh(intf, argc, argv))
+ return -1;
+ break;
+ default:
+ print_strs(nm_cmd_vals, "Node Manager Interface commands", LOG_ERR, 0);
+ break;
+ }
return 0;
}