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