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 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 != 0) { 196 lprintf(LOG_ERR, "Invalid completion code received: %s", 197 val2str(rsp->ccode, completion_code_vals)); 198 } else if (rsp->data_len < 5) { 199 lprintf(LOG_ERR, "Invalid response length %d", 200 rsp->data_len); 201 } else if (rsp->data[0] != GROUP_EXT_VITA) { 202 lprintf(LOG_ERR, "Invalid group extension %#x", 203 rsp->data[0]); 204 } else if ((rsp->data[3] & 0x03) != 0) { 205 lprintf(LOG_ERR, "Unknown VSO Standard %d", 206 (rsp->data[3] & 0x03)); 207 } else if ((rsp->data[4] & 0x0F) != 1) { 208 lprintf(LOG_ERR, "Unknown VSO Specification Revision %d.%d", 209 (rsp->data[4] & 0x0F), (rsp->data[4] >> 4)); 210 } else { 211 vita_avail = 1; 212 lprintf(LOG_INFO, "Discovered VITA 46.11 Revision %d.%d", 213 (rsp->data[4] & 0x0F), (rsp->data[4] >> 4)); 214 } 215 216 return vita_avail; 217 } 218 219 uint8_t 220 ipmi_vita_ipmb_address(struct ipmi_intf *intf) 221 { 222 struct ipmi_rq req; 223 struct ipmi_rs *rsp; 224 unsigned char msg_data; 225 226 memset(&req, 0, sizeof(req)); 227 228 req.msg.netfn = IPMI_NETFN_PICMG; 229 req.msg.cmd = VITA_GET_FRU_ADDRESS_INFO_CMD; 230 req.msg.data = &msg_data; 231 req.msg.data_len = 1; 232 233 msg_data = GROUP_EXT_VITA; 234 235 rsp = intf->sendrecv(intf, &req); 236 237 if (rsp == NULL) { 238 lprintf(LOG_ERR, "No valid response received"); 239 } else if (rsp->ccode != 0) { 240 lprintf(LOG_ERR, "Invalid completion code received: %s", 241 val2str(rsp->ccode, completion_code_vals)); 242 } else if (rsp->data_len < 7) { 243 lprintf(LOG_ERR, "Invalid response length %d", 244 rsp->data_len); 245 } else if (rsp->data[0] != GROUP_EXT_VITA) { 246 lprintf(LOG_ERR, "Invalid group extension %#x", 247 rsp->data[0]); 248 } else { 249 return rsp->data[2]; 250 } 251 252 return 0; 253 } 254 255 static int 256 ipmi_vita_getaddr(struct ipmi_intf *intf, int argc, char **argv) 257 { 258 struct ipmi_rs *rsp; 259 struct ipmi_rq req; 260 unsigned char msg_data[2]; 261 262 memset(&req, 0, sizeof(req)); 263 264 req.msg.netfn = IPMI_NETFN_PICMG; 265 req.msg.cmd = VITA_GET_FRU_ADDRESS_INFO_CMD; 266 req.msg.data = msg_data; 267 req.msg.data_len = 2; 268 269 msg_data[0] = GROUP_EXT_VITA; /* VITA identifier */ 270 msg_data[1] = 0; /* default FRU ID */ 271 272 if (argc > 0) { 273 /* validate and get FRU Device ID */ 274 if (is_fru_id(argv[0], &msg_data[1]) != 0) { 275 return -1; 276 } 277 } 278 279 rsp = intf->sendrecv(intf, &req); 280 281 if (rsp == NULL) { 282 lprintf(LOG_ERR, "No valid response received"); 283 return -1; 284 } else if (rsp->ccode != 0) { 285 lprintf(LOG_ERR, "Invalid completion code received: %s", 286 val2str(rsp->ccode, completion_code_vals)); 287 return -1; 288 } else if (rsp->data_len < 7) { 289 lprintf(LOG_ERR, "Invalid response length %d", 290 rsp->data_len); 291 return -1; 292 } else if (rsp->data[0] != GROUP_EXT_VITA) { 293 lprintf(LOG_ERR, "Invalid group extension %#x", 294 rsp->data[0]); 295 return -1; 296 } 297 298 printf("Hardware Address : 0x%02x\n", rsp->data[1]); 299 printf("IPMB-0 Address : 0x%02x\n", rsp->data[2]); 300 printf("FRU ID : 0x%02x\n", rsp->data[4]); 301 printf("Site ID : 0x%02x\n", rsp->data[5]); 302 printf("Site Type : %s\n", val2str(rsp->data[6], 303 vita_site_types)); 304 if (rsp->data_len > 8) { 305 printf("Channel 7 Address: 0x%02x\n", rsp->data[8]); 306 } 307 308 return 0; 309 } 310 311 static int 312 ipmi_vita_get_vso_capabilities(struct ipmi_intf *intf) 313 { 314 struct ipmi_rs *rsp; 315 struct ipmi_rq req; 316 unsigned char msg_data, tmp; 317 318 memset(&req, 0, sizeof(req)); 319 320 req.msg.netfn = IPMI_NETFN_PICMG; 321 req.msg.cmd = VITA_GET_VSO_CAPABILITIES_CMD; 322 req.msg.data = &msg_data; 323 req.msg.data_len = 1; 324 325 msg_data = GROUP_EXT_VITA; /* VITA identifier */ 326 327 rsp = intf->sendrecv(intf, &req); 328 329 if (rsp == NULL) { 330 lprintf(LOG_ERR, "No valid response received."); 331 return -1; 332 } else if (rsp->ccode != 0) { 333 lprintf(LOG_ERR, "Invalid completion code received: %s", 334 val2str(rsp->ccode, completion_code_vals)); 335 return -1; 336 } else if (rsp->data_len < 5) { 337 lprintf(LOG_ERR, "Invalid response length %d", rsp->data_len); 338 return -1; 339 } else if (rsp->data[0] != GROUP_EXT_VITA) { 340 lprintf(LOG_ERR, "Invalid group extension %#x", rsp->data[0]); 341 return -1; 342 } 343 344 printf("VSO Identifier : 0x%02x\n", rsp->data[0]); 345 printf("IPMC Identifier : 0x%02x\n", rsp->data[1]); 346 printf(" Tier %d\n", (rsp->data[1] & 0x03) + 1); 347 printf(" Layer %d\n", ((rsp->data[1] & 0x30) >> 4) + 1); 348 349 printf("IPMB Capabilities : 0x%02x\n", rsp->data[2]); 350 351 tmp = (rsp->data[2] & 0x30) >> 4; 352 353 printf(" Frequency %skHz\n", 354 tmp == 0 ? "100" : tmp == 1 ? "400" : "RESERVED"); 355 356 tmp = rsp->data[2] & 3; 357 358 if (tmp == 1) { 359 printf(" 2 IPMB interfaces supported\n"); 360 } else if (tmp == 0) { 361 printf(" 1 IPMB interface supported\n"); 362 } 363 364 printf("VSO Standard : %s\n", 365 (rsp->data[3] & 0x3) == 0 ? "VITA 46.11" : "RESERVED"); 366 367 printf("VSO Spec Revision : %d.%d\n", rsp->data[4] & 0xf, 368 rsp->data[4] >> 4); 369 370 printf("Max FRU Device ID : 0x%02x\n", rsp->data[5]); 371 printf("FRU Device ID : 0x%02x\n", rsp->data[6]); 372 373 return 0; 374 } 375 376 static int 377 ipmi_vita_set_fru_activation(struct ipmi_intf *intf, 378 char **argv, unsigned char command) 379 { 380 struct ipmi_rs *rsp; 381 struct ipmi_rq req; 382 unsigned char msg_data[3]; 383 384 memset(&req, 0, sizeof(req)); 385 386 req.msg.netfn = IPMI_NETFN_PICMG; 387 req.msg.cmd = VITA_SET_FRU_ACTIVATION_CMD; 388 req.msg.data = msg_data; 389 req.msg.data_len = 3; 390 391 msg_data[0] = GROUP_EXT_VITA; /* VITA identifier */ 392 if (is_fru_id(argv[0], &msg_data[1]) != 0) { /* FRU ID */ 393 return -1; 394 } 395 msg_data[2] = command; /* command */ 396 397 rsp = intf->sendrecv(intf, &req); 398 399 if (rsp == NULL) { 400 lprintf(LOG_ERR, "No valid response received."); 401 return -1; 402 } else if (rsp->ccode != 0) { 403 lprintf(LOG_ERR, "Invalid completion code received: %s", 404 val2str(rsp->ccode, completion_code_vals)); 405 return -1; 406 } else if (rsp->data_len < 1) { 407 lprintf(LOG_ERR, "Invalid response length %d", rsp->data_len); 408 return -1; 409 } else if (rsp->data[0] != GROUP_EXT_VITA) { 410 lprintf(LOG_ERR, "Invalid group extension %#x", rsp->data[0]); 411 return -1; 412 } 413 414 printf("FRU has been successfully %s\n", 415 command ? "activated" : "deactivated"); 416 417 return 0; 418 } 419 420 static int 421 ipmi_vita_get_fru_state_policy_bits(struct ipmi_intf *intf, char **argv) 422 { 423 struct ipmi_rs *rsp; 424 struct ipmi_rq req; 425 unsigned char msg_data[2]; 426 427 memset(&req, 0, sizeof(req)); 428 429 req.msg.netfn = IPMI_NETFN_PICMG; 430 req.msg.cmd = VITA_GET_FRU_STATE_POLICY_BITS_CMD; 431 req.msg.data = msg_data; 432 req.msg.data_len = 2; 433 434 msg_data[0] = GROUP_EXT_VITA; /* VITA identifier */ 435 if (is_fru_id(argv[0], &msg_data[1]) != 0) { /* FRU ID */ 436 return -1; 437 } 438 439 rsp = intf->sendrecv(intf, &req); 440 441 if (rsp == NULL) { 442 lprintf(LOG_ERR, "No valid response received."); 443 return -1; 444 } else if (rsp->ccode != 0) { 445 lprintf(LOG_ERR, "Invalid completion code received: %s", 446 val2str(rsp->ccode, completion_code_vals)); 447 return -1; 448 } else if (rsp->data_len < 2) { 449 lprintf(LOG_ERR, "Invalid response length %d", rsp->data_len); 450 return -1; 451 } else if (rsp->data[0] != GROUP_EXT_VITA) { 452 lprintf(LOG_ERR, "Invalid group extension %#x", rsp->data[0]); 453 return -1; 454 } 455 456 printf("FRU State Policy Bits: %xh\n", rsp->data[1]); 457 printf(" Default-Activation-Locked Policy Bit is %d\n", 458 rsp->data[1] & 0x08 ? 1 : 0); 459 printf(" Commanded-Deactivation-Ignored Policy Bit is %d\n", 460 rsp->data[1] & 0x04 ? 1 : 0); 461 printf(" Deactivation-Locked Policy Bit is %d\n", 462 rsp->data[1] & 0x02 ? 1 : 0); 463 printf(" Activation-Locked Policy Bit is %d\n", 464 rsp->data[1] & 0x01); 465 466 return 0; 467 } 468 469 static int 470 ipmi_vita_set_fru_state_policy_bits(struct ipmi_intf *intf, char **argv) 471 { 472 struct ipmi_rs *rsp; 473 struct ipmi_rq req; 474 unsigned char msg_data[4]; 475 476 memset(&req, 0, sizeof(req)); 477 478 req.msg.netfn = IPMI_NETFN_PICMG; 479 req.msg.cmd = VITA_SET_FRU_STATE_POLICY_BITS_CMD; 480 req.msg.data = msg_data; 481 req.msg.data_len = 4; 482 483 msg_data[0] = GROUP_EXT_VITA; /* VITA identifier */ 484 if (is_fru_id(argv[0], &msg_data[1]) != 0) { /* FRU ID */ 485 return -1; 486 } 487 if (str2uchar(argv[1], &msg_data[2]) != 0) { /* bits mask */ 488 return -1; 489 } 490 if (str2uchar(argv[2], &msg_data[3]) != 0) { /* bits */ 491 return -1; 492 } 493 494 rsp = intf->sendrecv(intf, &req); 495 496 if (rsp == NULL) { 497 lprintf(LOG_ERR, "No valid response received."); 498 return -1; 499 } else if (rsp->ccode != 0) { 500 lprintf(LOG_ERR, "Invalid completion code received: %s", 501 val2str(rsp->ccode, completion_code_vals)); 502 return -1; 503 } else if (rsp->data_len < 1) { 504 lprintf(LOG_ERR, "Invalid response length %d", rsp->data_len); 505 return -1; 506 } else if (rsp->data[0] != GROUP_EXT_VITA) { 507 lprintf(LOG_ERR, "Invalid group extension %#x", rsp->data[0]); 508 return -1; 509 } 510 511 printf("FRU state policy bits have been updated\n"); 512 513 return 0; 514 } 515 516 static int 517 ipmi_vita_get_led_properties(struct ipmi_intf *intf, char **argv) 518 { 519 struct ipmi_rs *rsp; 520 struct ipmi_rq req; 521 unsigned char msg_data[2]; 522 523 memset(&req, 0, sizeof(req)); 524 525 req.msg.netfn = IPMI_NETFN_PICMG; 526 req.msg.cmd = VITA_GET_FRU_LED_PROPERTIES_CMD; 527 req.msg.data = msg_data; 528 req.msg.data_len = 2; 529 530 msg_data[0] = GROUP_EXT_VITA; /* VITA identifier */ 531 if (is_fru_id(argv[0], &msg_data[1]) != 0) { /* FRU ID */ 532 return -1; 533 } 534 535 rsp = intf->sendrecv(intf, &req); 536 537 if (rsp == NULL) { 538 lprintf(LOG_ERR, "No valid response received."); 539 return -1; 540 } else if (rsp->ccode != 0) { 541 lprintf(LOG_ERR, "Invalid completion code received: %s", 542 val2str(rsp->ccode, completion_code_vals)); 543 return -1; 544 } else if (rsp->data_len < 3) { 545 lprintf(LOG_ERR, "Invalid response length %d", rsp->data_len); 546 return -1; 547 } else if (rsp->data[0] != GROUP_EXT_VITA) { 548 lprintf(LOG_ERR, "Invalid group extension %#x", rsp->data[0]); 549 return -1; 550 } 551 552 printf("LED Count: %#x\n", rsp->data[2]); 553 554 return 0; 555 } 556 557 static int 558 ipmi_vita_get_led_color_capabilities(struct ipmi_intf *intf, char **argv) 559 { 560 struct ipmi_rs *rsp; 561 struct ipmi_rq req; 562 unsigned char msg_data[3]; 563 int i; 564 565 memset(&req, 0, sizeof(req)); 566 567 req.msg.netfn = IPMI_NETFN_PICMG; 568 req.msg.cmd = VITA_GET_LED_COLOR_CAPABILITIES_CMD; 569 req.msg.data = msg_data; 570 req.msg.data_len = 3; 571 572 msg_data[0] = GROUP_EXT_VITA; /* VITA identifier */ 573 if (is_fru_id(argv[0], &msg_data[1]) != 0) { /* FRU ID */ 574 return -1; 575 } 576 if (str2uchar(argv[1], &msg_data[2]) != 0) { /* LED-ID */ 577 return -1; 578 } 579 580 rsp = intf->sendrecv(intf, &req); 581 582 if (rsp == NULL) { 583 lprintf(LOG_ERR, "No valid response received."); 584 return -1; 585 } else if (rsp->ccode != 0) { 586 lprintf(LOG_ERR, "Invalid completion code received: %s", 587 val2str(rsp->ccode, completion_code_vals)); 588 return -1; 589 } else if (rsp->data_len < 5) { 590 lprintf(LOG_ERR, "Invalid response length %d", rsp->data_len); 591 return -1; 592 } else if (rsp->data[0] != GROUP_EXT_VITA) { 593 lprintf(LOG_ERR, "Invalid group extension %#x", rsp->data[0]); 594 return -1; 595 } 596 597 printf("LED Color Capabilities: "); 598 for (i = 0; i < 8; i++) { 599 if (rsp->data[1] & (0x01 << i)) { 600 printf("%s, ", led_color_str[i]); 601 } 602 } 603 putchar('\n'); 604 605 printf("Default LED Color in\n"); 606 printf(" LOCAL control: %s\n", led_color_str[rsp->data[2]]); 607 printf(" OVERRIDE state: %s\n", led_color_str[rsp->data[3]]); 608 609 if (rsp->data_len == 5) { 610 printf("LED flags:\n"); 611 if (rsp->data[4] & 2) { 612 printf(" [HW RESTRICT]\n"); 613 } 614 if (rsp->data[4] & 1) { 615 printf(" [PAYLOAD PWR]\n"); 616 } 617 } 618 619 return 0; 620 } 621 622 static int 623 ipmi_vita_get_led_state(struct ipmi_intf *intf, char **argv) 624 { 625 struct ipmi_rs *rsp; 626 struct ipmi_rq req; 627 unsigned char msg_data[3]; 628 629 memset(&req, 0, sizeof(req)); 630 631 req.msg.netfn = IPMI_NETFN_PICMG; 632 req.msg.cmd = VITA_GET_FRU_LED_STATE_CMD; 633 req.msg.data = msg_data; 634 req.msg.data_len = 3; 635 636 msg_data[0] = GROUP_EXT_VITA; /* VITA identifier */ 637 if (is_fru_id(argv[0], &msg_data[1]) != 0) { /* FRU ID */ 638 return -1; 639 } 640 if (str2uchar(argv[1], &msg_data[2]) != 0) { /* LED-ID */ 641 return -1; 642 } 643 644 rsp = intf->sendrecv(intf, &req); 645 646 if (rsp == NULL) { 647 lprintf(LOG_ERR, "No valid response received."); 648 return -1; 649 } else if (rsp->ccode != 0) { 650 lprintf(LOG_ERR, "Invalid completion code received: %s", 651 val2str(rsp->ccode, completion_code_vals)); 652 return -1; 653 } else if (rsp->data_len < 5 654 || ((rsp->data[1] & 0x2) && rsp->data_len < 8) 655 || ((rsp->data[1] & 0x4) && rsp->data_len < 9)) { 656 lprintf(LOG_ERR, "Invalid response length %d", rsp->data_len); 657 return -1; 658 } else if (rsp->data[0] != GROUP_EXT_VITA) { 659 lprintf(LOG_ERR, "Invalid group extension %#x", rsp->data[0]); 660 return -1; 661 } 662 663 printf("LED states: %x\t", rsp->data[1]); 664 if (rsp->data[1] & 0x1) { 665 printf("[LOCAL CONTROL] "); 666 } 667 if (rsp->data[1] & 0x2) { 668 printf("[OVERRIDE] "); 669 } 670 if (rsp->data[1] & 0x4) { 671 printf("[LAMPTEST] "); 672 } 673 if (rsp->data[1] & 0x8) { 674 printf("[HW RESTRICT] "); 675 } 676 putchar('\n'); 677 678 if (rsp->data[1] & 1) { 679 printf(" Local Control function: %x\t", rsp->data[2]); 680 if (rsp->data[2] == 0x0) { 681 printf("[OFF]\n"); 682 } else if (rsp->data[2] == 0xff) { 683 printf("[ON]\n"); 684 } else { 685 printf("[BLINKING]\n"); 686 } 687 printf(" Local Control On-Duration: %x\n", rsp->data[3]); 688 printf(" Local Control Color: %x\t[%s]\n", 689 rsp->data[4], led_color_str[rsp->data[4] & 7]); 690 } 691 692 /* override state or lamp test */ 693 if (rsp->data[1] & 0x06) { 694 printf(" Override function: %x\t", rsp->data[5]); 695 if (rsp->data[5] == 0x0) { 696 printf("[OFF]\n"); 697 } else if (rsp->data[5] == 0xff) { 698 printf("[ON]\n"); 699 } else { 700 printf("[BLINKING]\n"); 701 } 702 printf(" Override On-Duration: %x\n", rsp->data[6]); 703 printf(" Override Color: %x\t[%s]\n", 704 rsp->data[7], led_color_str[rsp->data[7] & 7]); 705 if (rsp->data[1] == 0x04) { 706 printf(" Lamp test duration: %x\n", rsp->data[8]); 707 } 708 } 709 710 return 0; 711 } 712 713 static int 714 ipmi_vita_set_led_state(struct ipmi_intf *intf, char **argv) 715 { 716 struct ipmi_rs *rsp; 717 struct ipmi_rq req; 718 unsigned char msg_data[6]; 719 720 memset(&req, 0, sizeof(req)); 721 722 req.msg.netfn = IPMI_NETFN_PICMG; 723 req.msg.cmd = VITA_SET_FRU_LED_STATE_CMD; 724 req.msg.data = msg_data; 725 req.msg.data_len = 6; 726 727 msg_data[0] = GROUP_EXT_VITA; /* VITA identifier */ 728 if (is_fru_id(argv[0], &msg_data[1]) != 0) { /* FRU ID */ 729 return -1; 730 } 731 if (str2uchar(argv[1], &msg_data[2]) != 0) { /* LED-ID */ 732 return -1; 733 } 734 if (str2uchar(argv[2], &msg_data[3]) != 0) { /* LED function */ 735 return -1; 736 } 737 if (str2uchar(argv[3], &msg_data[4]) != 0) { /* LED on duration */ 738 return -1; 739 } 740 if (str2uchar(argv[4], &msg_data[5]) != 0) { /* LED color */ 741 return -1; 742 } 743 744 rsp = intf->sendrecv(intf, &req); 745 746 if (rsp == NULL) { 747 lprintf(LOG_ERR, "No valid response received."); 748 return -1; 749 } else if (rsp->ccode != 0) { 750 lprintf(LOG_ERR, "Invalid completion code received: %s", 751 val2str(rsp->ccode, completion_code_vals)); 752 return -1; 753 } else if (rsp->data_len < 1) { 754 lprintf(LOG_ERR, "Invalid response length %d", rsp->data_len); 755 return -1; 756 } else if (rsp->data[0] != GROUP_EXT_VITA) { 757 lprintf(LOG_ERR, "Invalid group extension %#x", rsp->data[0]); 758 return -1; 759 } 760 761 printf("LED state has been updated\n"); 762 763 return 0; 764 } 765 766 static int 767 ipmi_vita_fru_control(struct ipmi_intf *intf, char **argv) 768 { 769 struct ipmi_rs *rsp; 770 struct ipmi_rq req; 771 unsigned char msg_data[3]; 772 773 memset(&req, 0, sizeof(req)); 774 775 req.msg.netfn = IPMI_NETFN_PICMG; 776 req.msg.cmd = VITA_FRU_CONTROL_CMD; 777 req.msg.data = msg_data; 778 req.msg.data_len = 3; 779 780 msg_data[0] = GROUP_EXT_VITA; /* VITA identifier */ 781 if (is_fru_id(argv[0], &msg_data[1]) != 0) { /* FRU ID */ 782 return -1; 783 } 784 if (str2uchar(argv[1], &msg_data[2]) != 0) { /* control option */ 785 return -1; 786 } 787 788 printf("FRU Device Id: %d FRU Control Option: %s\n", msg_data[1], 789 val2str(msg_data[2], picmg_frucontrol_vals)); 790 791 rsp = intf->sendrecv(intf, &req); 792 793 if (rsp == NULL) { 794 lprintf(LOG_ERR, "No valid response received."); 795 return -1; 796 } else if (rsp->ccode != 0) { 797 lprintf(LOG_ERR, "Invalid completion code received: %s", 798 val2str(rsp->ccode, completion_code_vals)); 799 return -1; 800 } else if (rsp->data_len < 1) { 801 lprintf(LOG_ERR, "Invalid response length %d", rsp->data_len); 802 return -1; 803 } else if (rsp->data[0] != GROUP_EXT_VITA) { 804 lprintf(LOG_ERR, "Invalid group extension %#x", rsp->data[0]); 805 return -1; 806 } 807 808 printf("FRU Control: ok\n"); 809 810 return 0; 811 } 812 813 static int 814 ipmi_vita_get_cmd(int argc, char **argv) 815 { 816 if (argc < 1 || !strncmp(argv[0], "help", 4)) { 817 return VITA_CMD_HELP; 818 } 819 820 /* Get VSO Properties */ 821 if (!strncmp(argv[0], "properties", 10)) { 822 return VITA_CMD_PROPERTIES; 823 } 824 825 /* FRU Control command */ 826 if (!strncmp(argv[0], "frucontrol", 10)) { 827 return VITA_CMD_FRUCONTROL; 828 } 829 830 /* Get FRU Address Info command */ 831 if (!strncmp(argv[0], "addrinfo", 8)) { 832 return VITA_CMD_ADDRINFO; 833 } 834 835 /* Set FRU Activation (activate) command */ 836 if (!strncmp(argv[0], "activate", 8)) { 837 return VITA_CMD_ACTIVATE; 838 } 839 840 /* Set FRU Activation (deactivate) command */ 841 if (!strncmp(argv[0], "deactivate", 10)) { 842 return VITA_CMD_DEACTIVATE; 843 } 844 845 /* FRU State Policy Bits commands */ 846 if (!strncmp(argv[0], "policy", 6)) { 847 if (argc < 2) { 848 return VITA_CMD_UNKNOWN; 849 } 850 851 /* Get FRU State Policy Bits command */ 852 if (!strncmp(argv[1], "get", 3)) { 853 return VITA_CMD_POLICY_GET; 854 } 855 856 /* Set FRU State Policy Bits command */ 857 if (!strncmp(argv[1], "set", 3)) { 858 return VITA_CMD_POLICY_SET; 859 } 860 861 /* unknown command */ 862 return VITA_CMD_UNKNOWN; 863 } 864 865 /* FRU LED commands */ 866 if (!strncmp(argv[0], "led", 3)) { 867 if (argc < 2) { 868 return VITA_CMD_UNKNOWN; 869 } 870 871 /* FRU LED Get Properties */ 872 if (!strncmp(argv[1], "prop", 4)) { 873 return VITA_CMD_LED_PROP; 874 } 875 876 /* FRU LED Get Capabilities */ 877 if (!strncmp(argv[1], "cap", 3)) { 878 return VITA_CMD_LED_CAP; 879 } 880 881 /* FRU LED Get State */ 882 if (!strncmp(argv[1], "get", 3)) { 883 return VITA_CMD_LED_GET; 884 } 885 886 /* FRU LED Set State */ 887 if (!strncmp(argv[1], "set", 3)) { 888 return VITA_CMD_LED_SET; 889 } 890 891 /* unknown command */ 892 return VITA_CMD_UNKNOWN; 893 } 894 895 /* unknown command */ 896 return VITA_CMD_UNKNOWN; 897 } 898 899 int 900 ipmi_vita_main (struct ipmi_intf *intf, int argc, char **argv) 901 { 902 int rc = -1, show_help = 0; 903 int cmd = ipmi_vita_get_cmd(argc, argv); 904 905 switch (cmd) { 906 case VITA_CMD_HELP: 907 cmd = ipmi_vita_get_cmd(argc - 1, &argv[1]); 908 show_help = 1; 909 rc = 0; 910 break; 911 912 case VITA_CMD_PROPERTIES: 913 rc = ipmi_vita_get_vso_capabilities(intf); 914 break; 915 916 case VITA_CMD_FRUCONTROL: 917 if (argc > 2) { 918 rc = ipmi_vita_fru_control(intf, &argv[1]); 919 } else { 920 show_help = 1; 921 } 922 break; 923 924 case VITA_CMD_ADDRINFO: 925 rc = ipmi_vita_getaddr(intf, argc - 1, &argv[1]); 926 break; 927 928 case VITA_CMD_ACTIVATE: 929 if (argc > 1) { 930 rc = ipmi_vita_set_fru_activation(intf, &argv[1], 1); 931 } else { 932 show_help = 1; 933 } 934 break; 935 936 case VITA_CMD_DEACTIVATE: 937 if (argc > 1) { 938 rc = ipmi_vita_set_fru_activation(intf, &argv[1], 0); 939 } else { 940 show_help = 1; 941 } 942 break; 943 944 case VITA_CMD_POLICY_GET: 945 if (argc > 2) { 946 rc = ipmi_vita_get_fru_state_policy_bits(intf, 947 &argv[2]); 948 } else { 949 show_help = 1; 950 } 951 break; 952 953 case VITA_CMD_POLICY_SET: 954 if (argc > 4) { 955 rc = ipmi_vita_set_fru_state_policy_bits(intf, 956 &argv[2]); 957 } else { 958 show_help = 1; 959 } 960 break; 961 962 case VITA_CMD_LED_PROP: 963 if (argc > 2) { 964 rc = ipmi_vita_get_led_properties(intf, &argv[2]); 965 } else { 966 show_help = 1; 967 } 968 break; 969 970 case VITA_CMD_LED_CAP: 971 if (argc > 3) { 972 rc = ipmi_vita_get_led_color_capabilities(intf, 973 &argv[2]); 974 } else { 975 show_help = 1; 976 } 977 break; 978 979 case VITA_CMD_LED_GET: 980 if (argc > 3) { 981 rc = ipmi_vita_get_led_state(intf, &argv[2]); 982 } else { 983 show_help = 1; 984 } 985 break; 986 987 case VITA_CMD_LED_SET: 988 if (argc > 6) { 989 rc = ipmi_vita_set_led_state(intf, &argv[2]); 990 } else { 991 show_help = 1; 992 } 993 break; 994 default: 995 lprintf(LOG_NOTICE, "Unknown command"); 996 cmd = VITA_CMD_HELP; 997 show_help = 1; 998 break; 999 } 1000 1001 if (show_help) { 1002 lprintf(LOG_NOTICE, "%s", val2str(cmd, vita_help_strings)); 1003 } 1004 1005 return rc; 1006 } 1007