1 /*
2 * Copyright (c) 2014 Pigeon Point Systems. All right reserved
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * Redistribution of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 *
11 * Redistribution in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * Neither the name of Pigeon Point Systems, or the names of
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * This software is provided "AS IS, " without a warranty of any kind.
20 * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
21 * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
22 * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
23 * PIGEON POINT SYSTEMS ("PPS") AND ITS LICENSORS SHALL NOT BE LIABLE
24 * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
25 * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
26 * PPS OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
27 * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
28 * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
29 * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
30 * EVEN IF PPS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
31 */
32
33
34 #include <ipmitool/ipmi_intf.h>
35 #include <ipmitool/ipmi_picmg.h>
36 #include <ipmitool/ipmi_vita.h>
37 #include <ipmitool/ipmi_fru.h>
38 #include <ipmitool/ipmi_strings.h>
39 #include <ipmitool/log.h>
40
41 /* Handled VITA 46.11 commands */
42 #define VITA_CMD_HELP 0
43 #define VITA_CMD_PROPERTIES 1
44 #define VITA_CMD_FRUCONTROL 2
45 #define VITA_CMD_ADDRINFO 3
46 #define VITA_CMD_ACTIVATE 4
47 #define VITA_CMD_DEACTIVATE 5
48 #define VITA_CMD_POLICY_GET 6
49 #define VITA_CMD_POLICY_SET 7
50 #define VITA_CMD_LED_PROP 8
51 #define VITA_CMD_LED_CAP 9
52 #define VITA_CMD_LED_GET 10
53 #define VITA_CMD_LED_SET 11
54 #define VITA_CMD_UNKNOWN 255
55
56 /* VITA 46.11 Site Type strings */
57 static struct valstr vita_site_types[] = {
58 { VITA_FRONT_VPX_MODULE, "Front Loading VPX Plug-In Module" },
59 { VITA_POWER_ENTRY, "Power Entry Module" },
60 { VITA_CHASSIS_FRU, "Chassic FRU Information Module" },
61 { VITA_DEDICATED_CHMC, "Dedicated Chassis Manager" },
62 { VITA_FAN_TRAY, "Fan Tray" },
63 { VITA_FAN_TRAY_FILTER, "Fan Tray Filter" },
64 { VITA_ALARM_PANEL, "Alarm Panel" },
65 { VITA_XMC, "XMC" },
66 { VITA_VPX_RTM, "VPX Rear Transition Module" },
67 { VITA_FRONT_VME_MODULE, "Front Loading VME Plug-In Module" },
68 { VITA_FRONT_VXS_MODULE, "Front Loading VXS Plug-In Module" },
69 { VITA_POWER_SUPPLY, "Power Supply" },
70 { VITA_FRONT_VITA62_MODULE, "Front Loading VITA 62 Module\n" },
71 { VITA_71_MODULE, "VITA 71 Module\n" },
72 { VITA_FMC, "FMC\n" },
73 { 0, NULL }
74 };
75
76 /* VITA 46.11 command help strings */
77 static struct valstr vita_help_strings[] = {
78 {
79 VITA_CMD_HELP,
80 "VITA commands:\n"
81 " properties - get VSO properties\n"
82 " frucontrol - FRU control\n"
83 " addrinfo - get address information\n"
84 " activate - activate a FRU\n"
85 " deactivate - deactivate a FRU\n"
86 " policy get - get the FRU activation policy\n"
87 " policy set - set the FRU activation policy\n"
88 " led prop - get led properties\n"
89 " led cap - get led color capabilities\n"
90 " led get - get led state\n"
91 " led set - set led state"
92 },
93 {
94 VITA_CMD_FRUCONTROL,
95 "usage: frucontrol <FRU-ID> <OPTION>\n"
96 " OPTION: 0 - Cold Reset\n"
97 " 1 - Warm Reset\n"
98 " 2 - Graceful Reboot\n"
99 " 3 - Issue Diagnostic Interrupt"
100 },
101 {
102 VITA_CMD_ADDRINFO,
103 "usage: addrinfo [<FRU-ID>]"
104 },
105 {
106 VITA_CMD_ACTIVATE,
107 "usage: activate <FRU-ID>"
108 },
109 {
110 VITA_CMD_DEACTIVATE,
111 "usage: deactivate <FRU-ID>"
112 },
113 {
114 VITA_CMD_POLICY_GET,
115 "usage: policy get <FRU-ID>"
116 },
117 {
118 VITA_CMD_POLICY_SET,
119 "usage: policy set <FRU-ID> <MASK> <VALUE>\n"
120 " MASK: [3] affect the Default-Activation-Locked Policy Bit\n"
121 " [2] affect the Commanded-Deactivation-Ignored Policy Bit\n"
122 " [1] affect the Deactivation-Locked Policy Bit\n"
123 " [0] affect the Activation-Locked Policy Bit\n"
124 " VALUE: [3] value for the Default-Activation-Locked Policy Bit\n"
125 " [2] value for the Commanded-Deactivation-Ignored Policy Bit\n"
126 " [1] value for the Deactivation-Locked Policy Bit\n"
127 " [0] value for the Activation-Locked Policy Bit"
128 },
129 {
130 VITA_CMD_LED_PROP,
131 "usage: led prop <FRU-ID>"
132 },
133 {
134 VITA_CMD_LED_CAP,
135 "usage: led cap <FRU-ID> <LED-ID"
136 },
137 {
138 VITA_CMD_LED_GET,
139 "usage: led get <FRU-ID> <LED-ID",
140 },
141 {
142 VITA_CMD_LED_SET,
143 "usage: led set <FRU-ID> <LED-ID> <FUNCTION> <DURATION> <COLOR>\n"
144 " <FRU-ID>\n"
145 " <LED-ID> 0-0xFE: Specified LED\n"
146 " 0xFF: All LEDs under management control\n"
147 " <FUNCTION> 0: LED OFF override\n"
148 " 1 - 250: LED blinking override (off duration)\n"
149 " 251: LED Lamp Test\n"
150 " 252: LED restore to local control\n"
151 " 255: LED ON override\n"
152 " <DURATION> 1 - 127: LED Lamp Test / on duration\n"
153 " <COLOR> 1: BLUE\n"
154 " 2: RED\n"
155 " 3: GREEN\n"
156 " 4: AMBER\n"
157 " 5: ORANGE\n"
158 " 6: WHITE\n"
159 " 0xE: do not change\n"
160 " 0xF: use default color"
161 },
162 {
163 VITA_CMD_UNKNOWN,
164 "Unknown command"
165 },
166 { 0, NULL }
167 };
168
169 /* check if VITA 46.11 is supported */
170 uint8_t
vita_discover(struct ipmi_intf * intf)171 vita_discover(struct ipmi_intf *intf)
172 {
173 struct ipmi_rq req;
174 struct ipmi_rs *rsp;
175 unsigned char msg_data;
176 int vita_avail = 0;
177
178 memset(&req, 0, sizeof(req));
179
180 req.msg.netfn = IPMI_NETFN_PICMG;
181 req.msg.cmd = VITA_GET_VSO_CAPABILITIES_CMD;
182 req.msg.data = &msg_data;
183 req.msg.data_len = 1;
184
185 msg_data = GROUP_EXT_VITA;
186
187 lprintf(LOG_INFO, "Running Get VSO Capabilities my_addr %#x, "
188 "transit %#x, target %#x",
189 intf->my_addr, intf->transit_addr, intf->target_addr);
190
191 rsp = intf->sendrecv(intf, &req);
192
193 if (rsp == NULL) {
194 lprintf(LOG_ERR, "No valid response received");
195 } else if (rsp->ccode == 0xC1) {
196 lprintf(LOG_INFO, "Invalid completion code received: %s",
197 val2str(rsp->ccode, completion_code_vals));
198 } else if (rsp->ccode == 0xCC) {
199 lprintf(LOG_INFO, "Invalid data field received: %s",
200 val2str(rsp->ccode, completion_code_vals));
201 } else if (rsp->ccode != 0) {
202 lprintf(LOG_INFO, "Invalid completion code received: %s",
203 val2str(rsp->ccode, completion_code_vals));
204 } else if (rsp->data_len < 5) {
205 lprintf(LOG_INFO, "Invalid response length %d",
206 rsp->data_len);
207 } else if (rsp->data[0] != GROUP_EXT_VITA) {
208 lprintf(LOG_INFO, "Invalid group extension %#x",
209 rsp->data[0]);
210 } else if ((rsp->data[3] & 0x03) != 0) {
211 lprintf(LOG_INFO, "Unknown VSO Standard %d",
212 (rsp->data[3] & 0x03));
213 } else if ((rsp->data[4] & 0x0F) != 1) {
214 lprintf(LOG_INFO, "Unknown VSO Specification Revision %d.%d",
215 (rsp->data[4] & 0x0F), (rsp->data[4] >> 4));
216 } else {
217 vita_avail = 1;
218 lprintf(LOG_INFO, "Discovered VITA 46.11 Revision %d.%d",
219 (rsp->data[4] & 0x0F), (rsp->data[4] >> 4));
220 }
221
222 return vita_avail;
223 }
224
225 uint8_t
ipmi_vita_ipmb_address(struct ipmi_intf * intf)226 ipmi_vita_ipmb_address(struct ipmi_intf *intf)
227 {
228 struct ipmi_rq req;
229 struct ipmi_rs *rsp;
230 unsigned char msg_data;
231
232 memset(&req, 0, sizeof(req));
233
234 req.msg.netfn = IPMI_NETFN_PICMG;
235 req.msg.cmd = VITA_GET_FRU_ADDRESS_INFO_CMD;
236 req.msg.data = &msg_data;
237 req.msg.data_len = 1;
238
239 msg_data = GROUP_EXT_VITA;
240
241 rsp = intf->sendrecv(intf, &req);
242
243 if (rsp == NULL) {
244 lprintf(LOG_ERR, "No valid response received");
245 } else if (rsp->ccode != 0) {
246 lprintf(LOG_ERR, "Invalid completion code received: %s",
247 val2str(rsp->ccode, completion_code_vals));
248 } else if (rsp->data_len < 7) {
249 lprintf(LOG_ERR, "Invalid response length %d",
250 rsp->data_len);
251 } else if (rsp->data[0] != GROUP_EXT_VITA) {
252 lprintf(LOG_ERR, "Invalid group extension %#x",
253 rsp->data[0]);
254 } else {
255 return rsp->data[2];
256 }
257
258 return 0;
259 }
260
261 static int
ipmi_vita_getaddr(struct ipmi_intf * intf,int argc,char ** argv)262 ipmi_vita_getaddr(struct ipmi_intf *intf, int argc, char **argv)
263 {
264 struct ipmi_rs *rsp;
265 struct ipmi_rq req;
266 unsigned char msg_data[2];
267
268 memset(&req, 0, sizeof(req));
269
270 req.msg.netfn = IPMI_NETFN_PICMG;
271 req.msg.cmd = VITA_GET_FRU_ADDRESS_INFO_CMD;
272 req.msg.data = msg_data;
273 req.msg.data_len = 2;
274
275 msg_data[0] = GROUP_EXT_VITA; /* VITA identifier */
276 msg_data[1] = 0; /* default FRU ID */
277
278 if (argc > 0) {
279 /* validate and get FRU Device ID */
280 if (is_fru_id(argv[0], &msg_data[1]) != 0) {
281 return -1;
282 }
283 }
284
285 rsp = intf->sendrecv(intf, &req);
286
287 if (rsp == NULL) {
288 lprintf(LOG_ERR, "No valid response received");
289 return -1;
290 } else if (rsp->ccode != 0) {
291 lprintf(LOG_ERR, "Invalid completion code received: %s",
292 val2str(rsp->ccode, completion_code_vals));
293 return -1;
294 } else if (rsp->data_len < 7) {
295 lprintf(LOG_ERR, "Invalid response length %d",
296 rsp->data_len);
297 return -1;
298 } else if (rsp->data[0] != GROUP_EXT_VITA) {
299 lprintf(LOG_ERR, "Invalid group extension %#x",
300 rsp->data[0]);
301 return -1;
302 }
303
304 printf("Hardware Address : 0x%02x\n", rsp->data[1]);
305 printf("IPMB-0 Address : 0x%02x\n", rsp->data[2]);
306 printf("FRU ID : 0x%02x\n", rsp->data[4]);
307 printf("Site ID : 0x%02x\n", rsp->data[5]);
308 printf("Site Type : %s\n", val2str(rsp->data[6],
309 vita_site_types));
310 if (rsp->data_len > 8) {
311 printf("Channel 7 Address: 0x%02x\n", rsp->data[8]);
312 }
313
314 return 0;
315 }
316
317 static int
ipmi_vita_get_vso_capabilities(struct ipmi_intf * intf)318 ipmi_vita_get_vso_capabilities(struct ipmi_intf *intf)
319 {
320 struct ipmi_rs *rsp;
321 struct ipmi_rq req;
322 unsigned char msg_data, tmp;
323
324 memset(&req, 0, sizeof(req));
325
326 req.msg.netfn = IPMI_NETFN_PICMG;
327 req.msg.cmd = VITA_GET_VSO_CAPABILITIES_CMD;
328 req.msg.data = &msg_data;
329 req.msg.data_len = 1;
330
331 msg_data = GROUP_EXT_VITA; /* VITA identifier */
332
333 rsp = intf->sendrecv(intf, &req);
334
335 if (rsp == NULL) {
336 lprintf(LOG_ERR, "No valid response received.");
337 return -1;
338 } else if (rsp->ccode != 0) {
339 lprintf(LOG_ERR, "Invalid completion code received: %s",
340 val2str(rsp->ccode, completion_code_vals));
341 return -1;
342 } else if (rsp->data_len < 5) {
343 lprintf(LOG_ERR, "Invalid response length %d", rsp->data_len);
344 return -1;
345 } else if (rsp->data[0] != GROUP_EXT_VITA) {
346 lprintf(LOG_ERR, "Invalid group extension %#x", rsp->data[0]);
347 return -1;
348 }
349
350 printf("VSO Identifier : 0x%02x\n", rsp->data[0]);
351 printf("IPMC Identifier : 0x%02x\n", rsp->data[1]);
352 printf(" Tier %d\n", (rsp->data[1] & 0x03) + 1);
353 printf(" Layer %d\n", ((rsp->data[1] & 0x30) >> 4) + 1);
354
355 printf("IPMB Capabilities : 0x%02x\n", rsp->data[2]);
356
357 tmp = (rsp->data[2] & 0x30) >> 4;
358
359 printf(" Frequency %skHz\n",
360 tmp == 0 ? "100" : tmp == 1 ? "400" : "RESERVED");
361
362 tmp = rsp->data[2] & 3;
363
364 if (tmp == 1) {
365 printf(" 2 IPMB interfaces supported\n");
366 } else if (tmp == 0) {
367 printf(" 1 IPMB interface supported\n");
368 }
369
370 printf("VSO Standard : %s\n",
371 (rsp->data[3] & 0x3) == 0 ? "VITA 46.11" : "RESERVED");
372
373 printf("VSO Spec Revision : %d.%d\n", rsp->data[4] & 0xf,
374 rsp->data[4] >> 4);
375
376 printf("Max FRU Device ID : 0x%02x\n", rsp->data[5]);
377 printf("FRU Device ID : 0x%02x\n", rsp->data[6]);
378
379 return 0;
380 }
381
382 static int
ipmi_vita_set_fru_activation(struct ipmi_intf * intf,char ** argv,unsigned char command)383 ipmi_vita_set_fru_activation(struct ipmi_intf *intf,
384 char **argv, unsigned char command)
385 {
386 struct ipmi_rs *rsp;
387 struct ipmi_rq req;
388 unsigned char msg_data[3];
389
390 memset(&req, 0, sizeof(req));
391
392 req.msg.netfn = IPMI_NETFN_PICMG;
393 req.msg.cmd = VITA_SET_FRU_ACTIVATION_CMD;
394 req.msg.data = msg_data;
395 req.msg.data_len = 3;
396
397 msg_data[0] = GROUP_EXT_VITA; /* VITA identifier */
398 if (is_fru_id(argv[0], &msg_data[1]) != 0) { /* FRU ID */
399 return -1;
400 }
401 msg_data[2] = command; /* command */
402
403 rsp = intf->sendrecv(intf, &req);
404
405 if (rsp == NULL) {
406 lprintf(LOG_ERR, "No valid response received.");
407 return -1;
408 } else if (rsp->ccode != 0) {
409 lprintf(LOG_ERR, "Invalid completion code received: %s",
410 val2str(rsp->ccode, completion_code_vals));
411 return -1;
412 } else if (rsp->data_len < 1) {
413 lprintf(LOG_ERR, "Invalid response length %d", rsp->data_len);
414 return -1;
415 } else if (rsp->data[0] != GROUP_EXT_VITA) {
416 lprintf(LOG_ERR, "Invalid group extension %#x", rsp->data[0]);
417 return -1;
418 }
419
420 printf("FRU has been successfully %s\n",
421 command ? "activated" : "deactivated");
422
423 return 0;
424 }
425
426 static int
ipmi_vita_get_fru_state_policy_bits(struct ipmi_intf * intf,char ** argv)427 ipmi_vita_get_fru_state_policy_bits(struct ipmi_intf *intf, char **argv)
428 {
429 struct ipmi_rs *rsp;
430 struct ipmi_rq req;
431 unsigned char msg_data[2];
432
433 memset(&req, 0, sizeof(req));
434
435 req.msg.netfn = IPMI_NETFN_PICMG;
436 req.msg.cmd = VITA_GET_FRU_STATE_POLICY_BITS_CMD;
437 req.msg.data = msg_data;
438 req.msg.data_len = 2;
439
440 msg_data[0] = GROUP_EXT_VITA; /* VITA identifier */
441 if (is_fru_id(argv[0], &msg_data[1]) != 0) { /* FRU ID */
442 return -1;
443 }
444
445 rsp = intf->sendrecv(intf, &req);
446
447 if (rsp == NULL) {
448 lprintf(LOG_ERR, "No valid response received.");
449 return -1;
450 } else if (rsp->ccode != 0) {
451 lprintf(LOG_ERR, "Invalid completion code received: %s",
452 val2str(rsp->ccode, completion_code_vals));
453 return -1;
454 } else if (rsp->data_len < 2) {
455 lprintf(LOG_ERR, "Invalid response length %d", rsp->data_len);
456 return -1;
457 } else if (rsp->data[0] != GROUP_EXT_VITA) {
458 lprintf(LOG_ERR, "Invalid group extension %#x", rsp->data[0]);
459 return -1;
460 }
461
462 printf("FRU State Policy Bits: %xh\n", rsp->data[1]);
463 printf(" Default-Activation-Locked Policy Bit is %d\n",
464 rsp->data[1] & 0x08 ? 1 : 0);
465 printf(" Commanded-Deactivation-Ignored Policy Bit is %d\n",
466 rsp->data[1] & 0x04 ? 1 : 0);
467 printf(" Deactivation-Locked Policy Bit is %d\n",
468 rsp->data[1] & 0x02 ? 1 : 0);
469 printf(" Activation-Locked Policy Bit is %d\n",
470 rsp->data[1] & 0x01);
471
472 return 0;
473 }
474
475 static int
ipmi_vita_set_fru_state_policy_bits(struct ipmi_intf * intf,char ** argv)476 ipmi_vita_set_fru_state_policy_bits(struct ipmi_intf *intf, char **argv)
477 {
478 struct ipmi_rs *rsp;
479 struct ipmi_rq req;
480 unsigned char msg_data[4];
481
482 memset(&req, 0, sizeof(req));
483
484 req.msg.netfn = IPMI_NETFN_PICMG;
485 req.msg.cmd = VITA_SET_FRU_STATE_POLICY_BITS_CMD;
486 req.msg.data = msg_data;
487 req.msg.data_len = 4;
488
489 msg_data[0] = GROUP_EXT_VITA; /* VITA identifier */
490 if (is_fru_id(argv[0], &msg_data[1]) != 0) { /* FRU ID */
491 return -1;
492 }
493 if (str2uchar(argv[1], &msg_data[2]) != 0) { /* bits mask */
494 return -1;
495 }
496 if (str2uchar(argv[2], &msg_data[3]) != 0) { /* bits */
497 return -1;
498 }
499
500 rsp = intf->sendrecv(intf, &req);
501
502 if (rsp == NULL) {
503 lprintf(LOG_ERR, "No valid response received.");
504 return -1;
505 } else if (rsp->ccode != 0) {
506 lprintf(LOG_ERR, "Invalid completion code received: %s",
507 val2str(rsp->ccode, completion_code_vals));
508 return -1;
509 } else if (rsp->data_len < 1) {
510 lprintf(LOG_ERR, "Invalid response length %d", rsp->data_len);
511 return -1;
512 } else if (rsp->data[0] != GROUP_EXT_VITA) {
513 lprintf(LOG_ERR, "Invalid group extension %#x", rsp->data[0]);
514 return -1;
515 }
516
517 printf("FRU state policy bits have been updated\n");
518
519 return 0;
520 }
521
522 static int
ipmi_vita_get_led_properties(struct ipmi_intf * intf,char ** argv)523 ipmi_vita_get_led_properties(struct ipmi_intf *intf, char **argv)
524 {
525 struct ipmi_rs *rsp;
526 struct ipmi_rq req;
527 unsigned char msg_data[2];
528
529 memset(&req, 0, sizeof(req));
530
531 req.msg.netfn = IPMI_NETFN_PICMG;
532 req.msg.cmd = VITA_GET_FRU_LED_PROPERTIES_CMD;
533 req.msg.data = msg_data;
534 req.msg.data_len = 2;
535
536 msg_data[0] = GROUP_EXT_VITA; /* VITA identifier */
537 if (is_fru_id(argv[0], &msg_data[1]) != 0) { /* FRU ID */
538 return -1;
539 }
540
541 rsp = intf->sendrecv(intf, &req);
542
543 if (rsp == NULL) {
544 lprintf(LOG_ERR, "No valid response received.");
545 return -1;
546 } else if (rsp->ccode != 0) {
547 lprintf(LOG_ERR, "Invalid completion code received: %s",
548 val2str(rsp->ccode, completion_code_vals));
549 return -1;
550 } else if (rsp->data_len < 3) {
551 lprintf(LOG_ERR, "Invalid response length %d", rsp->data_len);
552 return -1;
553 } else if (rsp->data[0] != GROUP_EXT_VITA) {
554 lprintf(LOG_ERR, "Invalid group extension %#x", rsp->data[0]);
555 return -1;
556 }
557
558 printf("LED Count: %#x\n", rsp->data[2]);
559
560 return 0;
561 }
562
563 static int
ipmi_vita_get_led_color_capabilities(struct ipmi_intf * intf,char ** argv)564 ipmi_vita_get_led_color_capabilities(struct ipmi_intf *intf, char **argv)
565 {
566 struct ipmi_rs *rsp;
567 struct ipmi_rq req;
568 unsigned char msg_data[3];
569 int i;
570
571 memset(&req, 0, sizeof(req));
572
573 req.msg.netfn = IPMI_NETFN_PICMG;
574 req.msg.cmd = VITA_GET_LED_COLOR_CAPABILITIES_CMD;
575 req.msg.data = msg_data;
576 req.msg.data_len = 3;
577
578 msg_data[0] = GROUP_EXT_VITA; /* VITA identifier */
579 if (is_fru_id(argv[0], &msg_data[1]) != 0) { /* FRU ID */
580 return -1;
581 }
582 if (str2uchar(argv[1], &msg_data[2]) != 0) { /* LED-ID */
583 return -1;
584 }
585
586 rsp = intf->sendrecv(intf, &req);
587
588 if (rsp == NULL) {
589 lprintf(LOG_ERR, "No valid response received.");
590 return -1;
591 } else if (rsp->ccode != 0) {
592 lprintf(LOG_ERR, "Invalid completion code received: %s",
593 val2str(rsp->ccode, completion_code_vals));
594 return -1;
595 } else if (rsp->data_len < 5) {
596 lprintf(LOG_ERR, "Invalid response length %d", rsp->data_len);
597 return -1;
598 } else if (rsp->data[0] != GROUP_EXT_VITA) {
599 lprintf(LOG_ERR, "Invalid group extension %#x", rsp->data[0]);
600 return -1;
601 }
602
603 printf("LED Color Capabilities: ");
604 for (i = 0; i < 8; i++) {
605 if (rsp->data[1] & (0x01 << i)) {
606 printf("%s, ", led_color_str[i]);
607 }
608 }
609 putchar('\n');
610
611 printf("Default LED Color in\n");
612 printf(" LOCAL control: %s\n", led_color_str[rsp->data[2]]);
613 printf(" OVERRIDE state: %s\n", led_color_str[rsp->data[3]]);
614
615 if (rsp->data_len == 5) {
616 printf("LED flags:\n");
617 if (rsp->data[4] & 2) {
618 printf(" [HW RESTRICT]\n");
619 }
620 if (rsp->data[4] & 1) {
621 printf(" [PAYLOAD PWR]\n");
622 }
623 }
624
625 return 0;
626 }
627
628 static int
ipmi_vita_get_led_state(struct ipmi_intf * intf,char ** argv)629 ipmi_vita_get_led_state(struct ipmi_intf *intf, char **argv)
630 {
631 struct ipmi_rs *rsp;
632 struct ipmi_rq req;
633 unsigned char msg_data[3];
634
635 memset(&req, 0, sizeof(req));
636
637 req.msg.netfn = IPMI_NETFN_PICMG;
638 req.msg.cmd = VITA_GET_FRU_LED_STATE_CMD;
639 req.msg.data = msg_data;
640 req.msg.data_len = 3;
641
642 msg_data[0] = GROUP_EXT_VITA; /* VITA identifier */
643 if (is_fru_id(argv[0], &msg_data[1]) != 0) { /* FRU ID */
644 return -1;
645 }
646 if (str2uchar(argv[1], &msg_data[2]) != 0) { /* LED-ID */
647 return -1;
648 }
649
650 rsp = intf->sendrecv(intf, &req);
651
652 if (rsp == NULL) {
653 lprintf(LOG_ERR, "No valid response received.");
654 return -1;
655 } else if (rsp->ccode != 0) {
656 lprintf(LOG_ERR, "Invalid completion code received: %s",
657 val2str(rsp->ccode, completion_code_vals));
658 return -1;
659 } else if (rsp->data_len < 5
660 || ((rsp->data[1] & 0x2) && rsp->data_len < 8)
661 || ((rsp->data[1] & 0x4) && rsp->data_len < 9)) {
662 lprintf(LOG_ERR, "Invalid response length %d", rsp->data_len);
663 return -1;
664 } else if (rsp->data[0] != GROUP_EXT_VITA) {
665 lprintf(LOG_ERR, "Invalid group extension %#x", rsp->data[0]);
666 return -1;
667 }
668
669 printf("LED states: %x\t", rsp->data[1]);
670 if (rsp->data[1] & 0x1) {
671 printf("[LOCAL CONTROL] ");
672 }
673 if (rsp->data[1] & 0x2) {
674 printf("[OVERRIDE] ");
675 }
676 if (rsp->data[1] & 0x4) {
677 printf("[LAMPTEST] ");
678 }
679 if (rsp->data[1] & 0x8) {
680 printf("[HW RESTRICT] ");
681 }
682 putchar('\n');
683
684 if (rsp->data[1] & 1) {
685 printf(" Local Control function: %x\t", rsp->data[2]);
686 if (rsp->data[2] == 0x0) {
687 printf("[OFF]\n");
688 } else if (rsp->data[2] == 0xff) {
689 printf("[ON]\n");
690 } else {
691 printf("[BLINKING]\n");
692 }
693 printf(" Local Control On-Duration: %x\n", rsp->data[3]);
694 printf(" Local Control Color: %x\t[%s]\n",
695 rsp->data[4], led_color_str[rsp->data[4] & 7]);
696 }
697
698 /* override state or lamp test */
699 if (rsp->data[1] & 0x06) {
700 printf(" Override function: %x\t", rsp->data[5]);
701 if (rsp->data[5] == 0x0) {
702 printf("[OFF]\n");
703 } else if (rsp->data[5] == 0xff) {
704 printf("[ON]\n");
705 } else {
706 printf("[BLINKING]\n");
707 }
708 printf(" Override On-Duration: %x\n", rsp->data[6]);
709 printf(" Override Color: %x\t[%s]\n",
710 rsp->data[7], led_color_str[rsp->data[7] & 7]);
711 if (rsp->data[1] == 0x04) {
712 printf(" Lamp test duration: %x\n", rsp->data[8]);
713 }
714 }
715
716 return 0;
717 }
718
719 static int
ipmi_vita_set_led_state(struct ipmi_intf * intf,char ** argv)720 ipmi_vita_set_led_state(struct ipmi_intf *intf, char **argv)
721 {
722 struct ipmi_rs *rsp;
723 struct ipmi_rq req;
724 unsigned char msg_data[6];
725
726 memset(&req, 0, sizeof(req));
727
728 req.msg.netfn = IPMI_NETFN_PICMG;
729 req.msg.cmd = VITA_SET_FRU_LED_STATE_CMD;
730 req.msg.data = msg_data;
731 req.msg.data_len = 6;
732
733 msg_data[0] = GROUP_EXT_VITA; /* VITA identifier */
734 if (is_fru_id(argv[0], &msg_data[1]) != 0) { /* FRU ID */
735 return -1;
736 }
737 if (str2uchar(argv[1], &msg_data[2]) != 0) { /* LED-ID */
738 return -1;
739 }
740 if (str2uchar(argv[2], &msg_data[3]) != 0) { /* LED function */
741 return -1;
742 }
743 if (str2uchar(argv[3], &msg_data[4]) != 0) { /* LED on duration */
744 return -1;
745 }
746 if (str2uchar(argv[4], &msg_data[5]) != 0) { /* LED color */
747 return -1;
748 }
749
750 rsp = intf->sendrecv(intf, &req);
751
752 if (rsp == NULL) {
753 lprintf(LOG_ERR, "No valid response received.");
754 return -1;
755 } else if (rsp->ccode != 0) {
756 lprintf(LOG_ERR, "Invalid completion code received: %s",
757 val2str(rsp->ccode, completion_code_vals));
758 return -1;
759 } else if (rsp->data_len < 1) {
760 lprintf(LOG_ERR, "Invalid response length %d", rsp->data_len);
761 return -1;
762 } else if (rsp->data[0] != GROUP_EXT_VITA) {
763 lprintf(LOG_ERR, "Invalid group extension %#x", rsp->data[0]);
764 return -1;
765 }
766
767 printf("LED state has been updated\n");
768
769 return 0;
770 }
771
772 static int
ipmi_vita_fru_control(struct ipmi_intf * intf,char ** argv)773 ipmi_vita_fru_control(struct ipmi_intf *intf, char **argv)
774 {
775 struct ipmi_rs *rsp;
776 struct ipmi_rq req;
777 unsigned char msg_data[3];
778
779 memset(&req, 0, sizeof(req));
780
781 req.msg.netfn = IPMI_NETFN_PICMG;
782 req.msg.cmd = VITA_FRU_CONTROL_CMD;
783 req.msg.data = msg_data;
784 req.msg.data_len = 3;
785
786 msg_data[0] = GROUP_EXT_VITA; /* VITA identifier */
787 if (is_fru_id(argv[0], &msg_data[1]) != 0) { /* FRU ID */
788 return -1;
789 }
790 if (str2uchar(argv[1], &msg_data[2]) != 0) { /* control option */
791 return -1;
792 }
793
794 printf("FRU Device Id: %d FRU Control Option: %s\n", msg_data[1],
795 val2str(msg_data[2], picmg_frucontrol_vals));
796
797 rsp = intf->sendrecv(intf, &req);
798
799 if (rsp == NULL) {
800 lprintf(LOG_ERR, "No valid response received.");
801 return -1;
802 } else if (rsp->ccode != 0) {
803 lprintf(LOG_ERR, "Invalid completion code received: %s",
804 val2str(rsp->ccode, completion_code_vals));
805 return -1;
806 } else if (rsp->data_len < 1) {
807 lprintf(LOG_ERR, "Invalid response length %d", rsp->data_len);
808 return -1;
809 } else if (rsp->data[0] != GROUP_EXT_VITA) {
810 lprintf(LOG_ERR, "Invalid group extension %#x", rsp->data[0]);
811 return -1;
812 }
813
814 printf("FRU Control: ok\n");
815
816 return 0;
817 }
818
819 static int
ipmi_vita_get_cmd(int argc,char ** argv)820 ipmi_vita_get_cmd(int argc, char **argv)
821 {
822 if (argc < 1 || !strncmp(argv[0], "help", 4)) {
823 return VITA_CMD_HELP;
824 }
825
826 /* Get VSO Properties */
827 if (!strncmp(argv[0], "properties", 10)) {
828 return VITA_CMD_PROPERTIES;
829 }
830
831 /* FRU Control command */
832 if (!strncmp(argv[0], "frucontrol", 10)) {
833 return VITA_CMD_FRUCONTROL;
834 }
835
836 /* Get FRU Address Info command */
837 if (!strncmp(argv[0], "addrinfo", 8)) {
838 return VITA_CMD_ADDRINFO;
839 }
840
841 /* Set FRU Activation (activate) command */
842 if (!strncmp(argv[0], "activate", 8)) {
843 return VITA_CMD_ACTIVATE;
844 }
845
846 /* Set FRU Activation (deactivate) command */
847 if (!strncmp(argv[0], "deactivate", 10)) {
848 return VITA_CMD_DEACTIVATE;
849 }
850
851 /* FRU State Policy Bits commands */
852 if (!strncmp(argv[0], "policy", 6)) {
853 if (argc < 2) {
854 return VITA_CMD_UNKNOWN;
855 }
856
857 /* Get FRU State Policy Bits command */
858 if (!strncmp(argv[1], "get", 3)) {
859 return VITA_CMD_POLICY_GET;
860 }
861
862 /* Set FRU State Policy Bits command */
863 if (!strncmp(argv[1], "set", 3)) {
864 return VITA_CMD_POLICY_SET;
865 }
866
867 /* unknown command */
868 return VITA_CMD_UNKNOWN;
869 }
870
871 /* FRU LED commands */
872 if (!strncmp(argv[0], "led", 3)) {
873 if (argc < 2) {
874 return VITA_CMD_UNKNOWN;
875 }
876
877 /* FRU LED Get Properties */
878 if (!strncmp(argv[1], "prop", 4)) {
879 return VITA_CMD_LED_PROP;
880 }
881
882 /* FRU LED Get Capabilities */
883 if (!strncmp(argv[1], "cap", 3)) {
884 return VITA_CMD_LED_CAP;
885 }
886
887 /* FRU LED Get State */
888 if (!strncmp(argv[1], "get", 3)) {
889 return VITA_CMD_LED_GET;
890 }
891
892 /* FRU LED Set State */
893 if (!strncmp(argv[1], "set", 3)) {
894 return VITA_CMD_LED_SET;
895 }
896
897 /* unknown command */
898 return VITA_CMD_UNKNOWN;
899 }
900
901 /* unknown command */
902 return VITA_CMD_UNKNOWN;
903 }
904
905 int
ipmi_vita_main(struct ipmi_intf * intf,int argc,char ** argv)906 ipmi_vita_main (struct ipmi_intf *intf, int argc, char **argv)
907 {
908 int rc = -1, show_help = 0;
909 int cmd = ipmi_vita_get_cmd(argc, argv);
910
911 switch (cmd) {
912 case VITA_CMD_HELP:
913 cmd = ipmi_vita_get_cmd(argc - 1, &argv[1]);
914 show_help = 1;
915 rc = 0;
916 break;
917
918 case VITA_CMD_PROPERTIES:
919 rc = ipmi_vita_get_vso_capabilities(intf);
920 break;
921
922 case VITA_CMD_FRUCONTROL:
923 if (argc > 2) {
924 rc = ipmi_vita_fru_control(intf, &argv[1]);
925 } else {
926 show_help = 1;
927 }
928 break;
929
930 case VITA_CMD_ADDRINFO:
931 rc = ipmi_vita_getaddr(intf, argc - 1, &argv[1]);
932 break;
933
934 case VITA_CMD_ACTIVATE:
935 if (argc > 1) {
936 rc = ipmi_vita_set_fru_activation(intf, &argv[1], 1);
937 } else {
938 show_help = 1;
939 }
940 break;
941
942 case VITA_CMD_DEACTIVATE:
943 if (argc > 1) {
944 rc = ipmi_vita_set_fru_activation(intf, &argv[1], 0);
945 } else {
946 show_help = 1;
947 }
948 break;
949
950 case VITA_CMD_POLICY_GET:
951 if (argc > 2) {
952 rc = ipmi_vita_get_fru_state_policy_bits(intf,
953 &argv[2]);
954 } else {
955 show_help = 1;
956 }
957 break;
958
959 case VITA_CMD_POLICY_SET:
960 if (argc > 4) {
961 rc = ipmi_vita_set_fru_state_policy_bits(intf,
962 &argv[2]);
963 } else {
964 show_help = 1;
965 }
966 break;
967
968 case VITA_CMD_LED_PROP:
969 if (argc > 2) {
970 rc = ipmi_vita_get_led_properties(intf, &argv[2]);
971 } else {
972 show_help = 1;
973 }
974 break;
975
976 case VITA_CMD_LED_CAP:
977 if (argc > 3) {
978 rc = ipmi_vita_get_led_color_capabilities(intf,
979 &argv[2]);
980 } else {
981 show_help = 1;
982 }
983 break;
984
985 case VITA_CMD_LED_GET:
986 if (argc > 3) {
987 rc = ipmi_vita_get_led_state(intf, &argv[2]);
988 } else {
989 show_help = 1;
990 }
991 break;
992
993 case VITA_CMD_LED_SET:
994 if (argc > 6) {
995 rc = ipmi_vita_set_led_state(intf, &argv[2]);
996 } else {
997 show_help = 1;
998 }
999 break;
1000 default:
1001 lprintf(LOG_NOTICE, "Unknown command");
1002 cmd = VITA_CMD_HELP;
1003 show_help = 1;
1004 break;
1005 }
1006
1007 if (show_help) {
1008 lprintf(LOG_NOTICE, "%s", val2str(cmd, vita_help_strings));
1009 }
1010
1011 return rc;
1012 }
1013