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 == 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_ERR, "Invalid completion code received: %s", 203 val2str(rsp->ccode, completion_code_vals)); 204 } else if (rsp->data_len < 5) { 205 lprintf(LOG_ERR, "Invalid response length %d", 206 rsp->data_len); 207 } else if (rsp->data[0] != GROUP_EXT_VITA) { 208 lprintf(LOG_ERR, "Invalid group extension %#x", 209 rsp->data[0]); 210 } else if ((rsp->data[3] & 0x03) != 0) { 211 lprintf(LOG_ERR, "Unknown VSO Standard %d", 212 (rsp->data[3] & 0x03)); 213 } else if ((rsp->data[4] & 0x0F) != 1) { 214 lprintf(LOG_ERR, "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 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 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 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 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 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 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 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 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 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 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 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 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 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