1 /* 2 * Copyright (c) 2003 Sun Microsystems, Inc. All Rights 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 Sun Microsystems, Inc. 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 * SUN MICROSYSTEMS, INC. ("SUN") 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 * SUN 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 SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 31 */ 32 33 #include <stdlib.h> 34 #include <string.h> 35 #include <stdio.h> 36 #include <time.h> 37 38 #include <ipmitool/helper.h> 39 #include <ipmitool/log.h> 40 #include <ipmitool/bswap.h> 41 #include <ipmitool/ipmi.h> 42 #include <ipmitool/ipmi_intf.h> 43 #include <ipmitool/ipmi_mc.h> 44 #include <ipmitool/ipmi_strings.h> 45 46 extern int verbose; 47 48 static int ipmi_sysinfo_main(struct ipmi_intf *intf, int argc, char ** argv, 49 int is_set); 50 static void printf_sysinfo_usage(int full_help); 51 52 /* ipmi_mc_reset - attempt to reset an MC 53 * 54 * @intf: ipmi interface 55 * @cmd: reset command to send 56 * BMC_WARM_RESET or 57 * BMC_COLD_RESET 58 * 59 * returns 0 on success 60 * returns -1 on error 61 */ 62 static int 63 ipmi_mc_reset(struct ipmi_intf * intf, int cmd) 64 { 65 struct ipmi_rs * rsp; 66 struct ipmi_rq req; 67 68 if( !intf->opened ) 69 intf->open(intf); 70 71 memset(&req, 0, sizeof(req)); 72 req.msg.netfn = IPMI_NETFN_APP; 73 req.msg.cmd = cmd; 74 req.msg.data_len = 0; 75 76 if (cmd == BMC_COLD_RESET) 77 intf->noanswer = 1; 78 79 rsp = intf->sendrecv(intf, &req); 80 81 if (cmd == BMC_COLD_RESET) 82 intf->abort = 1; 83 84 if (cmd == BMC_COLD_RESET && rsp == NULL) { 85 /* This is expected. See 20.2 Cold Reset Command, p.243, IPMIv2.0 rev1.0 */ 86 } else if (rsp == NULL) { 87 lprintf(LOG_ERR, "MC reset command failed."); 88 return (-1); 89 } else if (rsp->ccode > 0) { 90 lprintf(LOG_ERR, "MC reset command failed: %s", 91 val2str(rsp->ccode, completion_code_vals)); 92 return (-1); 93 } 94 95 printf("Sent %s reset command to MC\n", 96 (cmd == BMC_WARM_RESET) ? "warm" : "cold"); 97 98 return 0; 99 } 100 101 #ifdef HAVE_PRAGMA_PACK 102 #pragma pack(1) 103 #endif 104 struct bmc_enables_data { 105 #if WORDS_BIGENDIAN 106 uint8_t oem2 : 1; 107 uint8_t oem1 : 1; 108 uint8_t oem0 : 1; 109 uint8_t __reserved : 1; 110 uint8_t system_event_log : 1; 111 uint8_t event_msgbuf : 1; 112 uint8_t event_msgbuf_intr : 1; 113 uint8_t receive_msg_intr : 1; 114 #else 115 uint8_t receive_msg_intr : 1; 116 uint8_t event_msgbuf_intr : 1; 117 uint8_t event_msgbuf : 1; 118 uint8_t system_event_log : 1; 119 uint8_t __reserved : 1; 120 uint8_t oem0 : 1; 121 uint8_t oem1 : 1; 122 uint8_t oem2 : 1; 123 #endif 124 } ATTRIBUTE_PACKING; 125 #ifdef HAVE_PRAGMA_PACK 126 #pragma pack(0) 127 #endif 128 129 struct bitfield_data { 130 const char * name; 131 const char * desc; 132 uint32_t mask; 133 }; 134 135 struct bitfield_data mc_enables_bf[] = { 136 { 137 name: "recv_msg_intr", 138 desc: "Receive Message Queue Interrupt", 139 mask: 1<<0, 140 }, 141 { 142 name: "event_msg_intr", 143 desc: "Event Message Buffer Full Interrupt", 144 mask: 1<<1, 145 }, 146 { 147 name: "event_msg", 148 desc: "Event Message Buffer", 149 mask: 1<<2, 150 }, 151 { 152 name: "system_event_log", 153 desc: "System Event Logging", 154 mask: 1<<3, 155 }, 156 { 157 name: "oem0", 158 desc: "OEM 0", 159 mask: 1<<5, 160 }, 161 { 162 name: "oem1", 163 desc: "OEM 1", 164 mask: 1<<6, 165 }, 166 { 167 name: "oem2", 168 desc: "OEM 2", 169 mask: 1<<7, 170 }, 171 { NULL }, 172 }; 173 174 static void 175 printf_mc_reset_usage(void) 176 { 177 lprintf(LOG_NOTICE, "usage: mc reset <warm|cold>"); 178 } /* printf_mc_reset_usage(void) */ 179 180 static void 181 printf_mc_usage(void) 182 { 183 struct bitfield_data * bf; 184 lprintf(LOG_NOTICE, "MC Commands:"); 185 lprintf(LOG_NOTICE, " reset <warm|cold>"); 186 lprintf(LOG_NOTICE, " guid"); 187 lprintf(LOG_NOTICE, " info"); 188 lprintf(LOG_NOTICE, " watchdog <get|reset|off>"); 189 lprintf(LOG_NOTICE, " selftest"); 190 lprintf(LOG_NOTICE, " getenables"); 191 lprintf(LOG_NOTICE, " setenables <option=on|off> ..."); 192 for (bf = mc_enables_bf; bf->name != NULL; bf++) { 193 lprintf(LOG_NOTICE, " %-20s %s", bf->name, bf->desc); 194 } 195 printf_sysinfo_usage(0); 196 } 197 198 static void 199 printf_sysinfo_usage(int full_help) 200 { 201 if (full_help != 0) 202 lprintf(LOG_NOTICE, "usage:"); 203 204 lprintf(LOG_NOTICE, " getsysinfo <argument>"); 205 206 if (full_help != 0) { 207 lprintf(LOG_NOTICE, 208 " Retrieves system info from BMC for given argument"); 209 } 210 211 lprintf(LOG_NOTICE, " setsysinfo <argument> <string>"); 212 213 if (full_help != 0) { 214 lprintf(LOG_NOTICE, 215 " Stores system info string for given argument to BMC"); 216 lprintf(LOG_NOTICE, ""); 217 lprintf(LOG_NOTICE, " Valid arguments are:"); 218 } 219 lprintf(LOG_NOTICE, 220 " system_fw_version System firmware (e.g. BIOS) version"); 221 lprintf(LOG_NOTICE, 222 " primary_os_name Primary operating system name"); 223 lprintf(LOG_NOTICE, " os_name Operating system name"); 224 lprintf(LOG_NOTICE, 225 " system_name System Name of server(vendor dependent)"); 226 lprintf(LOG_NOTICE, 227 " delloem_os_version Running version of operating system"); 228 lprintf(LOG_NOTICE, " delloem_url URL of BMC webserver"); 229 lprintf(LOG_NOTICE, ""); 230 } 231 232 static void 233 print_watchdog_usage(void) 234 { 235 lprintf(LOG_NOTICE, "usage: watchdog <command>:"); 236 lprintf(LOG_NOTICE, " get : Get Current Watchdog settings"); 237 lprintf(LOG_NOTICE, " reset : Restart Watchdog timer based on most recent settings"); 238 lprintf(LOG_NOTICE, " off : Shut off a running Watchdog timer"); 239 } 240 241 /* ipmi_mc_get_enables - print out MC enables 242 * 243 * @intf: ipmi inteface 244 * 245 * returns 0 on success 246 * returns -1 on error 247 */ 248 static int 249 ipmi_mc_get_enables(struct ipmi_intf * intf) 250 { 251 struct ipmi_rs * rsp; 252 struct ipmi_rq req; 253 struct bitfield_data * bf; 254 255 memset(&req, 0, sizeof(req)); 256 req.msg.netfn = IPMI_NETFN_APP; 257 req.msg.cmd = BMC_GET_GLOBAL_ENABLES; 258 259 rsp = intf->sendrecv(intf, &req); 260 if (rsp == NULL) { 261 lprintf(LOG_ERR, "Get Global Enables command failed"); 262 return -1; 263 } 264 if (rsp->ccode > 0) { 265 lprintf(LOG_ERR, "Get Global Enables command failed: %s", 266 val2str(rsp->ccode, completion_code_vals)); 267 return -1; 268 } 269 270 for (bf = mc_enables_bf; bf->name != NULL; bf++) { 271 printf("%-40s : %sabled\n", bf->desc, 272 rsp->data[0] & bf->mask ? "en" : "dis"); 273 } 274 275 return 0; 276 } 277 278 /* ipmi_mc_set_enables - set MC enable flags 279 * 280 * @intf: ipmi inteface 281 * @argc: argument count 282 * @argv: argument list 283 * 284 * returns 0 on success 285 * returns -1 on error 286 */ 287 static int 288 ipmi_mc_set_enables(struct ipmi_intf * intf, int argc, char ** argv) 289 { 290 struct ipmi_rs * rsp; 291 struct ipmi_rq req; 292 struct bitfield_data * bf; 293 uint8_t en; 294 int i; 295 296 if (argc < 1) { 297 printf_mc_usage(); 298 return (-1); 299 } 300 else if (strncmp(argv[0], "help", 4) == 0) { 301 printf_mc_usage(); 302 return 0; 303 } 304 305 memset(&req, 0, sizeof(req)); 306 req.msg.netfn = IPMI_NETFN_APP; 307 req.msg.cmd = BMC_GET_GLOBAL_ENABLES; 308 309 rsp = intf->sendrecv(intf, &req); 310 if (rsp == NULL) { 311 lprintf(LOG_ERR, "Get Global Enables command failed"); 312 return -1; 313 } 314 if (rsp->ccode > 0) { 315 lprintf(LOG_ERR, "Get Global Enables command failed: %s", 316 val2str(rsp->ccode, completion_code_vals)); 317 return -1; 318 } 319 320 en = rsp->data[0]; 321 322 for (i = 0; i < argc; i++) { 323 for (bf = mc_enables_bf; bf->name != NULL; bf++) { 324 int nl = strlen(bf->name); 325 if (strncmp(argv[i], bf->name, nl) != 0) 326 continue; 327 if (strncmp(argv[i]+nl+1, "off", 3) == 0) { 328 printf("Disabling %s\n", bf->desc); 329 en &= ~bf->mask; 330 } 331 else if (strncmp(argv[i]+nl+1, "on", 2) == 0) { 332 printf("Enabling %s\n", bf->desc); 333 en |= bf->mask; 334 } 335 else { 336 lprintf(LOG_ERR, "Unrecognized option: %s", argv[i]); 337 } 338 } 339 } 340 341 if (en == rsp->data[0]) { 342 printf("\nNothing to change...\n"); 343 ipmi_mc_get_enables(intf); 344 return 0; 345 } 346 347 req.msg.cmd = BMC_SET_GLOBAL_ENABLES; 348 req.msg.data = &en; 349 req.msg.data_len = 1; 350 351 rsp = intf->sendrecv(intf, &req); 352 if (rsp == NULL) { 353 lprintf(LOG_ERR, "Set Global Enables command failed"); 354 return -1; 355 } 356 else if (rsp->ccode > 0) { 357 lprintf(LOG_ERR, "Set Global Enables command failed: %s", 358 val2str(rsp->ccode, completion_code_vals)); 359 return -1; 360 } 361 362 printf("\nVerifying...\n"); 363 ipmi_mc_get_enables(intf); 364 365 return 0; 366 } 367 368 /* IPM Device, Get Device ID Command - Additional Device Support */ 369 const char *ipm_dev_adtl_dev_support[8] = { 370 "Sensor Device", /* bit 0 */ 371 "SDR Repository Device", /* bit 1 */ 372 "SEL Device", /* bit 2 */ 373 "FRU Inventory Device", /* ... */ 374 "IPMB Event Receiver", 375 "IPMB Event Generator", 376 "Bridge", 377 "Chassis Device" /* bit 7 */ 378 }; 379 380 /* ipmi_mc_get_deviceid - print information about this MC 381 * 382 * @intf: ipmi interface 383 * 384 * returns 0 on success 385 * returns -1 on error 386 */ 387 static int 388 ipmi_mc_get_deviceid(struct ipmi_intf * intf) 389 { 390 struct ipmi_rs * rsp; 391 struct ipmi_rq req; 392 struct ipm_devid_rsp *devid; 393 int i; 394 const char *product=NULL; 395 396 memset(&req, 0, sizeof(req)); 397 req.msg.netfn = IPMI_NETFN_APP; 398 req.msg.cmd = BMC_GET_DEVICE_ID; 399 req.msg.data_len = 0; 400 401 rsp = intf->sendrecv(intf, &req); 402 if (rsp == NULL) { 403 lprintf(LOG_ERR, "Get Device ID command failed"); 404 return -1; 405 } 406 if (rsp->ccode > 0) { 407 lprintf(LOG_ERR, "Get Device ID command failed: %s", 408 val2str(rsp->ccode, completion_code_vals)); 409 return -1; 410 } 411 412 devid = (struct ipm_devid_rsp *) rsp->data; 413 printf("Device ID : %i\n", 414 devid->device_id); 415 printf("Device Revision : %i\n", 416 devid->device_revision & IPM_DEV_DEVICE_ID_REV_MASK); 417 printf("Firmware Revision : %u.%02x\n", 418 devid->fw_rev1 & IPM_DEV_FWREV1_MAJOR_MASK, 419 devid->fw_rev2); 420 printf("IPMI Version : %x.%x\n", 421 IPM_DEV_IPMI_VERSION_MAJOR(devid->ipmi_version), 422 IPM_DEV_IPMI_VERSION_MINOR(devid->ipmi_version)); 423 printf("Manufacturer ID : %lu\n", 424 (long)IPM_DEV_MANUFACTURER_ID(devid->manufacturer_id)); 425 printf("Manufacturer Name : %s\n", 426 val2str( (long)IPM_DEV_MANUFACTURER_ID(devid->manufacturer_id), 427 ipmi_oem_info) ); 428 429 printf("Product ID : %u (0x%02x%02x)\n", 430 buf2short((uint8_t *)(devid->product_id)), 431 devid->product_id[1], devid->product_id[0]); 432 433 product=oemval2str(IPM_DEV_MANUFACTURER_ID(devid->manufacturer_id), 434 (devid->product_id[1]<<8)+devid->product_id[0], 435 ipmi_oem_product_info); 436 437 if (product!=NULL) { 438 printf("Product Name : %s\n", product); 439 } 440 441 printf("Device Available : %s\n", 442 (devid->fw_rev1 & IPM_DEV_FWREV1_AVAIL_MASK) ? 443 "no" : "yes"); 444 printf("Provides Device SDRs : %s\n", 445 (devid->device_revision & IPM_DEV_DEVICE_ID_SDR_MASK) ? 446 "yes" : "no"); 447 printf("Additional Device Support :\n"); 448 for (i = 0; i < IPM_DEV_ADTL_SUPPORT_BITS; i++) { 449 if (devid->adtl_device_support & (1 << i)) { 450 printf(" %s\n", ipm_dev_adtl_dev_support[i]); 451 } 452 } 453 if (rsp->data_len == sizeof(*devid)) { 454 printf("Aux Firmware Rev Info : \n"); 455 /* These values could be looked-up by vendor if documented, 456 * so we put them on individual lines for better treatment later 457 */ 458 printf(" 0x%02x\n 0x%02x\n 0x%02x\n 0x%02x\n", 459 devid->aux_fw_rev[0], 460 devid->aux_fw_rev[1], 461 devid->aux_fw_rev[2], 462 devid->aux_fw_rev[3]); 463 } 464 return 0; 465 } 466 467 /* Structure follow the IPMI V.2 Rev 1.0 468 * See Table 20-10 */ 469 #ifdef HAVE_PRAGMA_PACK 470 #pragma pack(1) 471 #endif 472 473 struct ipmi_guid { 474 uint32_t time_low; /* timestamp low field */ 475 uint16_t time_mid; /* timestamp middle field */ 476 uint16_t time_hi_and_version; /* timestamp high field and version number */ 477 uint8_t clock_seq_hi_variant;/* clock sequence high field and variant */ 478 uint8_t clock_seq_low; /* clock sequence low field */ 479 uint8_t node[6]; /* node */ 480 } ATTRIBUTE_PACKING; 481 #ifdef HAVE_PRAGMA_PACK 482 #pragma pack(0) 483 #endif 484 485 /* ipmi_mc_get_guid - print this MC GUID 486 * 487 * @intf: ipmi interface 488 * 489 * returns 0 on success 490 * returns -1 on error 491 */ 492 static int 493 ipmi_mc_get_guid(struct ipmi_intf * intf) 494 { 495 struct ipmi_rs * rsp; 496 struct ipmi_rq req; 497 struct ipmi_guid guid; 498 499 memset(&req, 0, sizeof(req)); 500 req.msg.netfn = IPMI_NETFN_APP; 501 req.msg.cmd = BMC_GET_GUID; 502 503 rsp = intf->sendrecv(intf, &req); 504 if (rsp == NULL) { 505 lprintf(LOG_ERR, "Get GUID command failed"); 506 return -1; 507 } 508 if (rsp->ccode > 0) { 509 lprintf(LOG_ERR, "Get GUID command failed: %s", 510 val2str(rsp->ccode, completion_code_vals)); 511 return -1; 512 } 513 514 if (rsp->data_len == sizeof(struct ipmi_guid)) { 515 char tbuf[40]; 516 time_t s; 517 memset(tbuf, 0, 40); 518 memset(&guid, 0, sizeof(struct ipmi_guid)); 519 memcpy(&guid, rsp->data, rsp->data_len); 520 521 /* Kipp - changed order of last field (node) to follow specification */ 522 printf("System GUID : %08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x\n", 523 guid.time_low, guid.time_mid, guid.time_hi_and_version, 524 guid.clock_seq_hi_variant << 8 | guid.clock_seq_low, 525 guid.node[0], guid.node[1], guid.node[2], 526 guid.node[3], guid.node[4], guid.node[5]); 527 528 s = (time_t)guid.time_low; /* Kipp - removed the BSWAP_32, it was not needed here */ 529 strftime(tbuf, sizeof(tbuf), "%m/%d/%Y %H:%M:%S", localtime(&s)); 530 printf("Timestamp : %s\n", tbuf); 531 } 532 else { 533 lprintf(LOG_ERR, "Invalid GUID length %d", rsp->data_len); 534 } 535 536 return 0; 537 } 538 539 /* ipmi_mc_get_selftest - returns and print selftest results 540 * 541 * @intf: ipmi interface 542 */ 543 static int ipmi_mc_get_selftest(struct ipmi_intf * intf) 544 { 545 int rv = 0; 546 struct ipmi_rs * rsp; 547 struct ipmi_rq req; 548 struct ipm_selftest_rsp *sft_res; 549 550 memset(&req, 0, sizeof(req)); 551 req.msg.netfn = IPMI_NETFN_APP; 552 req.msg.cmd = BMC_GET_SELF_TEST; 553 req.msg.data_len = 0; 554 555 rsp = intf->sendrecv(intf, &req); 556 if (!rsp) { 557 lprintf(LOG_ERR, "No response from devices\n"); 558 return -1; 559 } 560 561 if (rsp->ccode) { 562 lprintf(LOG_ERR, "Bad response: (%s)", 563 val2str(rsp->ccode, completion_code_vals)); 564 return -1; 565 } 566 567 sft_res = (struct ipm_selftest_rsp *) rsp->data; 568 569 if (sft_res->code == IPM_SFT_CODE_OK) { 570 printf("Selftest: passed\n"); 571 rv = 0; 572 } 573 574 else if (sft_res->code == IPM_SFT_CODE_NOT_IMPLEMENTED) { 575 printf("Selftest: not implemented\n"); 576 rv = -1; 577 } 578 579 else if (sft_res->code == IPM_SFT_CODE_DEV_CORRUPTED) { 580 printf("Selftest: device corrupted\n"); 581 rv = -1; 582 583 if (sft_res->test & IPM_SELFTEST_SEL_ERROR) { 584 printf(" -> SEL device not accessible\n"); 585 } 586 if (sft_res->test & IPM_SELFTEST_SDR_ERROR) { 587 printf(" -> SDR repository not accesible\n"); 588 } 589 if (sft_res->test & IPM_SELFTEST_FRU_ERROR) { 590 printf("FRU device not accessible\n"); 591 } 592 if (sft_res->test & IPM_SELFTEST_IPMB_ERROR) { 593 printf("IPMB signal lines do not respond\n"); 594 } 595 if (sft_res->test & IPM_SELFTEST_SDRR_EMPTY) { 596 printf("SDR repository empty\n"); 597 } 598 if (sft_res->test & IPM_SELFTEST_INTERNAL_USE) { 599 printf("Internal Use Area corrupted\n"); 600 } 601 if (sft_res->test & IPM_SELFTEST_FW_BOOTBLOCK) { 602 printf("Controller update boot block corrupted\n"); 603 } 604 if (sft_res->test & IPM_SELFTEST_FW_CORRUPTED) { 605 printf("controller operational firmware corrupted\n"); 606 } 607 } 608 609 else if (sft_res->code == IPM_SFT_CODE_FATAL_ERROR) { 610 printf("Selftest : fatal error\n"); 611 printf("Failure code : %02x\n", sft_res->test); 612 rv = -1; 613 } 614 615 else if (sft_res->code == IPM_SFT_CODE_RESERVED) { 616 printf("Selftest: N/A"); 617 rv = -1; 618 } 619 620 else { 621 printf("Selftest : device specific (%02Xh)\n", sft_res->code); 622 printf("Failure code : %02Xh\n", sft_res->test); 623 rv = 0; 624 } 625 626 return rv; 627 } 628 629 /* ipmi_mc_get_watchdog 630 * 631 * @intf: ipmi interface 632 * 633 * returns 0 on success 634 * returns -1 on error 635 */ 636 637 const char *wdt_use_string[8] = { 638 "Reserved", 639 "BIOS FRB2", 640 "BIOS/POST", 641 "OS Load", 642 "SMS/OS", 643 "OEM", 644 "Reserved", 645 "Reserved" 646 }; 647 648 const char *wdt_action_string[8] = { 649 "No action", 650 "Hard Reset", 651 "Power Down", 652 "Power Cycle", 653 "Reserved", 654 "Reserved", 655 "Reserved", 656 "Reserved" 657 }; 658 659 static int 660 ipmi_mc_get_watchdog(struct ipmi_intf * intf) 661 { 662 struct ipmi_rs * rsp; 663 struct ipmi_rq req; 664 struct ipm_get_watchdog_rsp * wdt_res; 665 666 memset(&req, 0, sizeof(req)); 667 req.msg.netfn = IPMI_NETFN_APP; 668 req.msg.cmd = BMC_GET_WATCHDOG_TIMER; 669 req.msg.data_len = 0; 670 671 rsp = intf->sendrecv(intf, &req); 672 if (rsp == NULL) { 673 lprintf(LOG_ERR, "Get Watchdog Timer command failed"); 674 return -1; 675 } 676 677 if (rsp->ccode) { 678 lprintf(LOG_ERR, "Get Watchdog Timer command failed: %s", 679 val2str(rsp->ccode, completion_code_vals)); 680 return -1; 681 } 682 683 wdt_res = (struct ipm_get_watchdog_rsp *) rsp->data; 684 685 printf("Watchdog Timer Use: %s (0x%02x)\n", 686 wdt_use_string[(wdt_res->timer_use & 0x07 )], wdt_res->timer_use); 687 printf("Watchdog Timer Is: %s\n", 688 wdt_res->timer_use & 0x40 ? "Started/Running" : "Stopped"); 689 printf("Watchdog Timer Actions: %s (0x%02x)\n", 690 wdt_action_string[(wdt_res->timer_actions&0x07)], wdt_res->timer_actions); 691 printf("Pre-timeout interval: %d seconds\n", wdt_res->pre_timeout); 692 printf("Timer Expiration Flags: 0x%02x\n", wdt_res->timer_use_exp); 693 printf("Initial Countdown: %i sec\n", 694 ((wdt_res->initial_countdown_msb << 8) | wdt_res->initial_countdown_lsb)/10); 695 printf("Present Countdown: %i sec\n", 696 (((wdt_res->present_countdown_msb << 8) | wdt_res->present_countdown_lsb)) / 10); 697 698 return 0; 699 } 700 701 /* ipmi_mc_shutoff_watchdog 702 * 703 * @intf: ipmi interface 704 * 705 * returns 0 on success 706 * returns -1 on error 707 */ 708 static int 709 ipmi_mc_shutoff_watchdog(struct ipmi_intf * intf) 710 { 711 struct ipmi_rs * rsp; 712 struct ipmi_rq req; 713 unsigned char msg_data[6]; 714 715 memset(&req, 0, sizeof(req)); 716 req.msg.netfn = IPMI_NETFN_APP; 717 req.msg.cmd = BMC_SET_WATCHDOG_TIMER; 718 req.msg.data = msg_data; 719 req.msg.data_len = 6; 720 721 /* 722 * The only set cmd we're allowing is to shut off the timer. 723 * Turning on the timer should be the job of the ipmi watchdog driver. 724 * See 'modinfo ipmi_watchdog' for more info. (NOTE: the reset 725 * command will restart the timer if it's already been initialized.) 726 * 727 * Out-of-band watchdog set commands can still be sent via the raw 728 * command interface but this is a very dangerous thing to do since 729 * a periodic "poke"/reset over a network is unreliable. This is 730 * not a recommended way to use the IPMI watchdog commands. 731 */ 732 733 msg_data[0] = IPM_WATCHDOG_SMS_OS; 734 msg_data[1] = IPM_WATCHDOG_NO_ACTION; 735 msg_data[2] = 0x00; /* pretimeout interval */ 736 msg_data[3] = IPM_WATCHDOG_CLEAR_SMS_OS; 737 msg_data[4] = 0xb8; /* countdown lsb (100 ms/count) */ 738 msg_data[5] = 0x0b; /* countdown msb - 5 mins */ 739 740 rsp = intf->sendrecv(intf, &req); 741 if (rsp == NULL) { 742 lprintf(LOG_ERR, "Watchdog Timer Shutoff command failed!"); 743 return -1; 744 } 745 746 if (rsp->ccode) { 747 lprintf(LOG_ERR, "Watchdog Timer Shutoff command failed! %s", 748 val2str(rsp->ccode, completion_code_vals)); 749 return -1; 750 } 751 752 printf("Watchdog Timer Shutoff successful -- timer stopped\n"); 753 return 0; 754 } 755 756 757 /* ipmi_mc_rst_watchdog 758 * 759 * @intf: ipmi interface 760 * 761 * returns 0 on success 762 * returns -1 on error 763 */ 764 static int 765 ipmi_mc_rst_watchdog(struct ipmi_intf * intf) 766 { 767 struct ipmi_rs * rsp; 768 struct ipmi_rq req; 769 770 memset(&req, 0, sizeof(req)); 771 req.msg.netfn = IPMI_NETFN_APP; 772 req.msg.cmd = BMC_RESET_WATCHDOG_TIMER; 773 req.msg.data_len = 0; 774 775 rsp = intf->sendrecv(intf, &req); 776 if (rsp == NULL) { 777 lprintf(LOG_ERR, "Reset Watchdog Timer command failed!"); 778 return -1; 779 } 780 781 if (rsp->ccode) { 782 lprintf(LOG_ERR, "Reset Watchdog Timer command failed: %s", 783 (rsp->ccode == IPM_WATCHDOG_RESET_ERROR) ? 784 "Attempt to reset unitialized watchdog" : 785 val2str(rsp->ccode, completion_code_vals)); 786 return -1; 787 } 788 789 printf("IPMI Watchdog Timer Reset - countdown restarted!\n"); 790 return 0; 791 } 792 793 /* ipmi_mc_main - top-level handler for MC functions 794 * 795 * @intf: ipmi interface 796 * @argc: number of arguments 797 * @argv: argument list 798 * 799 * returns 0 on success 800 * returns -1 on error 801 */ 802 int 803 ipmi_mc_main(struct ipmi_intf * intf, int argc, char ** argv) 804 { 805 int rc = 0; 806 807 if (argc < 1) { 808 lprintf(LOG_ERR, "Not enough parameters given."); 809 printf_mc_usage(); 810 rc = (-1); 811 } 812 else if (strncmp(argv[0], "help", 4) == 0) { 813 printf_mc_usage(); 814 rc = 0; 815 } 816 else if (strncmp(argv[0], "reset", 5) == 0) { 817 if (argc < 2) { 818 lprintf(LOG_ERR, "Not enough parameters given."); 819 printf_mc_reset_usage(); 820 rc = (-1); 821 } 822 else if (strncmp(argv[1], "help", 4) == 0) { 823 printf_mc_reset_usage(); 824 rc = 0; 825 } 826 else if (strncmp(argv[1], "cold", 4) == 0) { 827 rc = ipmi_mc_reset(intf, BMC_COLD_RESET); 828 } 829 else if (strncmp(argv[1], "warm", 4) == 0) { 830 rc = ipmi_mc_reset(intf, BMC_WARM_RESET); 831 } 832 else { 833 lprintf(LOG_ERR, "Invalid mc/bmc %s command: %s", argv[0], argv[1]); 834 printf_mc_reset_usage(); 835 rc = (-1); 836 } 837 } 838 else if (strncmp(argv[0], "info", 4) == 0) { 839 rc = ipmi_mc_get_deviceid(intf); 840 } 841 else if (strncmp(argv[0], "guid", 4) == 0) { 842 rc = ipmi_mc_get_guid(intf); 843 } 844 else if (strncmp(argv[0], "getenables", 10) == 0) { 845 rc = ipmi_mc_get_enables(intf); 846 } 847 else if (strncmp(argv[0], "setenables", 10) == 0) { 848 rc = ipmi_mc_set_enables(intf, argc-1, &(argv[1])); 849 } 850 else if (!strncmp(argv[0], "selftest", 8)) { 851 rc = ipmi_mc_get_selftest(intf); 852 } 853 else if (!strncmp(argv[0], "watchdog", 8)) { 854 if (argc < 2) { 855 lprintf(LOG_ERR, "Not enough parameters given."); 856 print_watchdog_usage(); 857 rc = (-1); 858 } 859 else if (strncmp(argv[1], "help", 4) == 0) { 860 print_watchdog_usage(); 861 rc = 0; 862 } 863 else if (strncmp(argv[1], "get", 3) == 0) { 864 rc = ipmi_mc_get_watchdog(intf); 865 } 866 else if(strncmp(argv[1], "off", 3) == 0) { 867 rc = ipmi_mc_shutoff_watchdog(intf); 868 } 869 else if(strncmp(argv[1], "reset", 5) == 0) { 870 rc = ipmi_mc_rst_watchdog(intf); 871 } 872 else { 873 lprintf(LOG_ERR, "Invalid mc/bmc %s command: %s", argv[0], argv[1]); 874 print_watchdog_usage(); 875 rc = (-1); 876 } 877 } 878 else if (strncmp(argv[0], "getsysinfo", 10) == 0) { 879 rc = ipmi_sysinfo_main(intf, argc, argv, 0); 880 } 881 else if (strncmp(argv[0], "setsysinfo", 10) == 0) { 882 rc = ipmi_sysinfo_main(intf, argc, argv, 1); 883 } 884 else { 885 lprintf(LOG_ERR, "Invalid mc/bmc command: %s", argv[0]); 886 printf_mc_usage(); 887 rc = (-1); 888 } 889 return rc; 890 } 891 892 /* 893 * sysinfo_param() - function converts sysinfo param to int 894 * 895 * @str - user input string 896 * @maxset - ? 897 * 898 * returns (-1) on error 899 * returns > 0 on success 900 */ 901 static int 902 sysinfo_param(const char *str, int *maxset) 903 { 904 if (!str || !maxset) 905 return (-1); 906 907 *maxset = 4; 908 if (!strcmp(str, "system_name")) 909 return IPMI_SYSINFO_HOSTNAME; 910 else if (!strcmp(str, "primary_os_name")) 911 return IPMI_SYSINFO_PRIMARY_OS_NAME; 912 else if (!strcmp(str, "os_name")) 913 return IPMI_SYSINFO_OS_NAME; 914 else if (!strcmp(str, "delloem_os_version")) 915 return IPMI_SYSINFO_DELL_OS_VERSION; 916 else if (!strcmp(str, "delloem_url")) { 917 *maxset = 2; 918 return IPMI_SYSINFO_DELL_URL; 919 } else if (!strcmp(str, "system_fw_version")) { 920 return IPMI_SYSINFO_SYSTEM_FW_VERSION; 921 } 922 923 return (-1); 924 } 925 926 /* 927 * ipmi_mc_getsysinfo() - function processes the IPMI Get System Info command 928 * 929 * @intf - ipmi interface 930 * @param - parameter eg. 0xC0..0xFF = OEM 931 * @block - number of block parameters 932 * @set - number of set parameters 933 * @len - length of buffer 934 * @buffer - pointer to buffer 935 * 936 * returns (-1) on failure 937 * returns 0 on success 938 * returns > 0 IPMI code 939 */ 940 int 941 ipmi_mc_getsysinfo(struct ipmi_intf * intf, int param, int block, int set, 942 int len, void *buffer) 943 { 944 uint8_t data[4]; 945 struct ipmi_rs *rsp = NULL; 946 struct ipmi_rq req = {0}; 947 948 memset(buffer, 0, len); 949 memset(data, 0, 4); 950 req.msg.netfn = IPMI_NETFN_APP; 951 req.msg.lun = 0; 952 req.msg.cmd = IPMI_GET_SYS_INFO; 953 req.msg.data_len = 4; 954 req.msg.data = data; 955 956 if (verbose > 1) 957 printf("getsysinfo: %.2x/%.2x/%.2x\n", param, block, set); 958 959 data[0] = 0; /* get/set */ 960 data[1] = param; 961 data[2] = block; 962 data[3] = set; 963 964 /* 965 * Format of get output is: 966 * u8 param_rev 967 * u8 selector 968 * u8 encoding bit[0-3]; 969 * u8 length 970 * u8 data0[14] 971 */ 972 rsp = intf->sendrecv(intf, &req); 973 if (rsp == NULL) 974 return (-1); 975 976 if (rsp->ccode == 0) { 977 if (len > rsp->data_len) 978 len = rsp->data_len; 979 if (len && buffer) 980 memcpy(buffer, rsp->data, len); 981 } 982 return rsp->ccode; 983 } 984 985 /* 986 * ipmi_mc_setsysinfo() - function processes the IPMI Set System Info command 987 * 988 * @intf - ipmi interface 989 * @len - length of buffer 990 * @buffer - pointer to buffer 991 * 992 * returns (-1) on failure 993 * returns 0 on success 994 * returns > 0 IPMI code 995 */ 996 int 997 ipmi_mc_setsysinfo(struct ipmi_intf * intf, int len, void *buffer) 998 { 999 struct ipmi_rs *rsp = NULL; 1000 struct ipmi_rq req = {0}; 1001 1002 req.msg.netfn = IPMI_NETFN_APP; 1003 req.msg.lun = 0; 1004 req.msg.cmd = IPMI_SET_SYS_INFO; 1005 req.msg.data_len = len; 1006 req.msg.data = buffer; 1007 1008 /* 1009 * Format of set input: 1010 * u8 param rev 1011 * u8 selector 1012 * u8 data1[16] 1013 */ 1014 rsp = intf->sendrecv(intf, &req); 1015 if (rsp != NULL) { 1016 return rsp->ccode; 1017 } 1018 return -1; 1019 } 1020 1021 static int 1022 ipmi_sysinfo_main(struct ipmi_intf *intf, int argc, char ** argv, int is_set) 1023 { 1024 char *str; 1025 unsigned char infostr[256]; 1026 unsigned char paramdata[18]; 1027 int len, maxset, param, pos, rc, set; 1028 1029 if (argc == 2 && strcmp(argv[1], "help") == 0) { 1030 printf_sysinfo_usage(1); 1031 return 0; 1032 } 1033 else if (argc < 2 || (is_set == 1 && argc < 3)) { 1034 lprintf(LOG_ERR, "Not enough parameters given."); 1035 printf_sysinfo_usage(1); 1036 return (-1); 1037 } 1038 1039 /* Get Parameters */ 1040 if ((param = sysinfo_param(argv[1], &maxset)) < 0) { 1041 lprintf(LOG_ERR, "Invalid mc/bmc %s command: %s", argv[0], argv[1]); 1042 printf_sysinfo_usage(1); 1043 return (-1); 1044 } 1045 1046 rc = 0; 1047 if (is_set != 0) { 1048 str = argv[2]; 1049 set = pos = 0; 1050 len = strlen(str); 1051 1052 /* first block holds 14 bytes, all others hold 16 */ 1053 if ((len + 2 + 15) / 16 >= maxset) 1054 len = (maxset * 16) - 2; 1055 1056 do { 1057 memset(paramdata, 0, sizeof(paramdata)); 1058 paramdata[0] = param; 1059 paramdata[1] = set; 1060 if (set == 0) { 1061 /* First block is special case */ 1062 paramdata[2] = 0; /* ascii encoding */ 1063 paramdata[3] = len; /* length */ 1064 strncpy(paramdata + 4, str + pos, IPMI_SYSINFO_SET0_SIZE); 1065 pos += IPMI_SYSINFO_SET0_SIZE; 1066 } 1067 else { 1068 strncpy(paramdata + 2, str + pos, IPMI_SYSINFO_SETN_SIZE); 1069 pos += IPMI_SYSINFO_SETN_SIZE; 1070 } 1071 rc = ipmi_mc_setsysinfo(intf, 18, paramdata); 1072 1073 if (rc) 1074 break; 1075 1076 set++; 1077 } while (pos < len); 1078 } 1079 else { 1080 memset(infostr, 0, sizeof(infostr)); 1081 /* Read blocks of data */ 1082 pos = 0; 1083 for (set = 0; set < maxset; set++) { 1084 rc = ipmi_mc_getsysinfo(intf, param, set, 0, 18, paramdata); 1085 1086 if (rc) 1087 break; 1088 1089 if (set == 0) { 1090 /* First block is special case */ 1091 if ((paramdata[2] & 0xF) == 0) { 1092 /* Determine max number of blocks to read */ 1093 maxset = ((paramdata[3] + 2) + 15) / 16; 1094 } 1095 memcpy(infostr + pos, paramdata + 4, IPMI_SYSINFO_SET0_SIZE); 1096 pos += IPMI_SYSINFO_SET0_SIZE; 1097 } 1098 else { 1099 memcpy(infostr + pos, paramdata + 2, IPMI_SYSINFO_SETN_SIZE); 1100 pos += IPMI_SYSINFO_SETN_SIZE; 1101 } 1102 } 1103 printf("%s\n", infostr); 1104 } 1105 if (rc < 0) { 1106 lprintf(LOG_ERR, "%s %s set %d command failed", argv[0], argv[1], set); 1107 } 1108 else if (rc == 0x80) { 1109 lprintf(LOG_ERR, "%s %s parameter not supported", argv[0], argv[1]); 1110 } 1111 else if (rc > 0) { 1112 lprintf(LOG_ERR, "%s command failed: %s", argv[0], 1113 val2str(rc, completion_code_vals)); 1114 } 1115 return rc; 1116 } 1117