1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 30 #include <ctype.h> 31 #include <dirent.h> 32 #include <errno.h> 33 #include <fcntl.h> 34 #include <langinfo.h> 35 #include <libintl.h> 36 #include <limits.h> 37 #include <locale.h> 38 #include <stdarg.h> 39 #include <stdio.h> 40 #include <stdlib.h> 41 #include <string.h> 42 #include <strings.h> 43 #include <sys/ddi.h> 44 #include <sys/mpt/mpi.h> 45 #include <sys/mpt/mpi_ioc.h> 46 #include <sys/stat.h> 47 #include <sys/types.h> 48 #include <sys/pci.h> 49 #include <unistd.h> 50 #include <sys/mnttab.h> 51 #include <sys/dkio.h> 52 #include <config_admin.h> 53 #include <sys/param.h> 54 #include <sys/raidioctl.h> 55 56 /* 57 * list of controllers to list 58 * setup like this: 59 * [ctrl_num] [status] 60 * 61 * where status is: 62 * RAID Found, 63 * No RAID Found 64 * RAID not supported on this controller 65 * Invalid Controller 66 */ 67 68 typedef enum { 69 RAID_FOUND = 0x0, 70 RAID_NOT_FOUND, 71 RAID_NOT_SUPPORTED, 72 RAID_INVALID_CTRL, 73 RAID_DONT_USE 74 } raidctl_errno_t; 75 76 /* For no-mixup indexing of info_ctrl */ 77 #define INFO_CTRL 0 78 #define INFO_STATUS 1 79 80 static int **info_ctrl = NULL; 81 /* Length of conrollers list */ 82 static int ctrl_nums = 0; 83 84 85 #define DEVDIR "/dev/rdsk" 86 87 #define DO_HW_RAID_NOP -1 88 #define DO_HW_RAID_INFO 0 89 #define DO_HW_RAID_CREATE 1 90 #define DO_HW_RAID_DELETE 2 91 #define DO_HW_RAID_FLASH 3 92 93 /* 94 * Error return codes 95 */ 96 #define SUCCESS 0 97 #define INVALID_ARG 1 98 #define FAILURE 2 99 100 /* 101 * FW Update Stuff 102 */ 103 104 /* signature and initial offset for PCI expansion rom images */ 105 #define PCIROM_SIG 0xaa55 /* offset 0h, length 2 bytes */ 106 #define PCIR_OFF 0x18 /* Pointer to PCI Data Structure */ 107 108 /* offsets in PCI data structure header */ 109 #define PCIR_DEVID 0x6 /* PCI device id */ 110 #define PCIR_CODETYPE 0x14 /* type of code (intel/fcode) */ 111 #define PCIR_INDICATOR 0x15 /* "last image" indicator */ 112 113 /* flags for image types */ 114 #define BIOS_IMAGE 0x1 115 #define FCODE_IMAGE 0x2 116 #define UNKNOWN_IMAGE 0x3 117 #define LAST_IMAGE 0x80 118 #define NOT_LAST_IMAGE 0 119 #define PCI_IMAGE_UNIT_SIZE 512 120 121 /* ID's and offsets for MPT Firmware images */ 122 #define FW_ROM_ID 0x5aea /* bytes 4 & 5 of file */ 123 #define FW_ROM_OFFSET_CHIP_TYPE 0x22 /* (U16) */ 124 #define FW_ROM_OFFSET_VERSION 0x24 /* (U16) */ 125 #define FW_ROM_OFFSET_VERSION_NAME 0x44 /* (32 U8) */ 126 127 /* Key to search for when looking for fcode version */ 128 #define FCODE_VERS_KEY1 0x12 129 #define FCODE_VERS_KEY2 0x7 130 #define BIOS_STR "LSI1030 SCSI Host Adapter BIOS Driver: " 131 132 /* get a word from a buffer (works with non-word aligned offsets) */ 133 #define gw(x) (((x)[0]) + (((x)[1]) << 8)) 134 135 /* Number of disks currently supported */ 136 #define N_DISKS 2 137 138 /* 139 * Function and strings to properly localize our prompt. 140 * So for example in german it would ask (ja/nein) or (yes/no) in 141 * english. 142 */ 143 static int yes(int c); 144 static char yeschr[SCHAR_MAX + 2]; 145 static char nochr[SCHAR_MAX +2]; 146 147 typedef struct raidlist { 148 raid_config_t raid_config; 149 int controller; 150 char devctl[MAXPATHLEN]; 151 struct raidlist *next; 152 } raidlist_t; 153 154 static raidlist_t *raids; 155 156 static void 157 usage(char *prog_name) 158 { 159 (void) fprintf(stderr, gettext("usage: %s\n"), prog_name); 160 161 (void) fprintf(stderr, gettext("usage: %s -c disk1 disk2\n"), 162 prog_name); 163 (void) fprintf(stderr, gettext("usage: %s -d disk1\n"), prog_name); 164 165 (void) fprintf(stderr, 166 gettext("usage: %s [-f] -F image_file controller \n"), 167 prog_name); 168 169 (void) fprintf(stderr, gettext("usage: %s -l [controller...]\n"), 170 prog_name); 171 172 (void) fprintf(stderr, gettext("example:\n")); 173 (void) fprintf(stderr, "%s -c c1t1d0 c1t2d0\n", prog_name); 174 (void) fprintf(stderr, "%s -d c1t1d0\n", prog_name); 175 (void) fprintf(stderr, "%s -F image 1\n", prog_name); 176 177 exit(1); 178 } 179 180 /* Make errno message more "user friendly" */ 181 static void 182 raidctl_error(char *str) 183 { 184 switch (errno) { 185 case EINVAL: 186 (void) fprintf(stderr, gettext("Error: " 187 "invalid argument would be returned\n")); 188 break; 189 case EIO: 190 case EFAULT: 191 (void) fprintf(stderr, 192 gettext("Error: Device inaccessible.\n")); 193 break; 194 case ENOTTY: 195 (void) fprintf(stderr, gettext("Error: " 196 "Device does not support requested action.\n")); 197 break; 198 default: 199 perror(str); 200 } 201 } 202 203 static int 204 get_link_path(const char *thing, char *buf) 205 { 206 if (readlink(thing, buf, MAXPATHLEN) < 0) 207 return (1); 208 return (0); 209 } 210 211 static int 212 get_ctrl_devctl(char *ctrl, char *b) 213 { 214 char devctl_buf[MAXPATHLEN]; 215 char *colon; 216 217 (void) strlcpy(devctl_buf, ctrl, MAXPATHLEN); 218 219 colon = strrchr(devctl_buf, ':'); 220 if (colon == NULL) 221 return (1); 222 223 *colon = 0; 224 (void) snprintf(devctl_buf, MAXPATHLEN, "%s:devctl", devctl_buf); 225 (void) strlcpy(b, devctl_buf, MAXPATHLEN); 226 return (0); 227 } 228 229 static int 230 get_devctl(char *disk, char *b) 231 { 232 char buf1[MAXPATHLEN] = {0}; 233 char devctl_buf[MAXPATHLEN]; 234 char *slash; 235 char devname[32]; 236 237 if (get_link_path(disk, buf1)) 238 return (1); 239 240 (void) strlcpy(devctl_buf, buf1, MAXPATHLEN); 241 242 slash = strrchr(devctl_buf, '/'); 243 if (slash == NULL) 244 return (1); 245 246 *slash = 0; 247 slash = strrchr(devctl_buf, '/'); 248 (void) strlcpy(devname, slash, 32); 249 *slash = 0; 250 251 (void) snprintf(devctl_buf, MAXPATHLEN, "%s%s:devctl", 252 devctl_buf, devname); 253 (void) strlcpy(b, devctl_buf, MAXPATHLEN); 254 return (0); 255 } 256 257 static int 258 already_there(int controller) 259 { 260 raidlist_t *curr = raids; 261 262 while (curr != NULL) { 263 if (curr->controller == controller) 264 return (1); 265 curr = curr->next; 266 } 267 268 return (0); 269 } 270 271 /* 272 * Display those controllers where RAID volumes were not found 273 */ 274 static void 275 print_no_raids() 276 { 277 int i, space = 0; 278 279 if (info_ctrl == NULL) 280 return; 281 282 for (i = 0; i < ctrl_nums; i++) { 283 /* Status of '0' means RAID exists at that controller */ 284 if (info_ctrl[i][INFO_STATUS] == RAID_FOUND || 285 info_ctrl[i][INFO_STATUS] == RAID_DONT_USE) 286 continue; 287 288 if (!space && raids != NULL) { 289 (void) printf("\n"); 290 space = 1; 291 } 292 293 /* switch statement used to enable gettext()'ing of text */ 294 switch (info_ctrl[i][INFO_STATUS]) { 295 case RAID_INVALID_CTRL: 296 (void) printf(gettext("Invalid controller '%d'\n"), 297 info_ctrl[i][INFO_CTRL]); 298 break; 299 case RAID_NOT_SUPPORTED: 300 (void) printf(gettext("No RAID supported " 301 "on controller '%d'\n"), 302 info_ctrl[i][INFO_CTRL]); 303 304 break; 305 default: 306 (void) printf(gettext("No RAID volumes found on " 307 "controller '%d'\n"), info_ctrl[i][INFO_CTRL]); 308 } 309 } 310 } 311 312 static void 313 add_raid_to_raidlist(char *ctrl_name, int controller) 314 { 315 raid_config_t config; 316 raidlist_t *curr; 317 char buf[MAXPATHLEN] = {0}; 318 char buf1[MAXPATHLEN] = {0}; 319 int fd; 320 int i; 321 322 if (readlink(ctrl_name, buf, sizeof (buf)) < 0) 323 return; 324 325 if (get_ctrl_devctl(buf, buf1)) 326 return; 327 328 /* 329 * If "-l" was specified, then only look at those controllers 330 * listed as part of the command line input. 331 */ 332 if (info_ctrl != NULL) { 333 int found = 0; 334 for (i = 0; i < ctrl_nums; i++) { 335 if (info_ctrl[i][INFO_STATUS] == RAID_DONT_USE) 336 continue; 337 if (controller == info_ctrl[i][INFO_CTRL]) { 338 found = 1; 339 break; 340 } 341 } 342 if (!found) 343 return; 344 } 345 346 fd = open(buf1, O_RDONLY); 347 if (fd == -1) { 348 if (info_ctrl != NULL) 349 info_ctrl[i][INFO_STATUS] = RAID_INVALID_CTRL; 350 return; 351 } 352 353 if (ioctl(fd, RAID_GETCONFIG, &config) < 0) { 354 if (info_ctrl != NULL) 355 info_ctrl[i][INFO_STATUS] = RAID_NOT_SUPPORTED; 356 (void) close(fd); 357 /* Fail silently */ 358 return; 359 } 360 (void) close(fd); 361 362 if (config.ndisks == 0) { 363 if (info_ctrl != NULL) 364 info_ctrl[i][INFO_STATUS] = RAID_NOT_FOUND; 365 return; 366 } 367 368 if (info_ctrl != NULL) 369 info_ctrl[i][INFO_STATUS] = RAID_FOUND; 370 371 if (raids == NULL) { 372 raids = (raidlist_t *)malloc(sizeof (raidlist_t)); 373 curr = raids; 374 } else { 375 if (already_there(controller)) { 376 return; 377 } 378 379 curr = raids; 380 /* Seek to the end */ 381 while (curr->next != NULL) 382 curr = curr->next; 383 384 curr->next = (raidlist_t *)malloc(sizeof (raidlist_t)); 385 curr = curr->next; 386 } 387 curr->next = NULL; 388 curr->controller = controller; 389 390 (void) strlcpy(curr->devctl, buf1, sizeof (curr->devctl)); 391 (void) fflush(stdout); 392 (void) memcpy(&curr->raid_config, &config, sizeof (raid_config_t)); 393 } 394 395 static void 396 print_header() 397 { 398 (void) printf(gettext("RAID\t\tRAID\t\tRAID\t\tDisk")); 399 (void) printf("\n"); 400 (void) printf(gettext("Volume\t\tStatus\t\tDisk\t\tStatus")); 401 (void) printf("\n"); 402 (void) printf("------------------------------------------------------"); 403 (void) printf("\n"); 404 } 405 406 static void 407 print_raidconfig(int c, raid_config_t config) 408 { 409 int i; 410 411 /* Get RAID Volume */ 412 (void) printf("c%dt%dd0\t\t", c, config.targetid); 413 414 /* Get RAID Info */ 415 if (config.flags & RAID_FLAG_RESYNCING && 416 config.state == RAID_STATE_DEGRADED) { 417 (void) printf(gettext("RESYNCING\t")); 418 } else if (config.state == RAID_STATE_DEGRADED) { 419 (void) printf(gettext("DEGRADED\t")); 420 } else if (config.state == RAID_STATE_OPTIMAL) { 421 (void) printf(gettext("OK\t\t")); 422 } else if (config.state == RAID_STATE_FAILED) { 423 (void) printf(gettext("FAILED\t\t")); 424 } else { 425 (void) printf(gettext("ERROR\t\t")); 426 } 427 428 /* Get RAID Disks */ 429 (void) printf("c%dt%dd0\t\t", c, config.disk[0]); 430 431 /* Get RAID Disk's Status */ 432 if (config.diskstatus[0] & RAID_DISKSTATUS_FAILED) { 433 (void) printf(gettext("FAILED\n")); 434 } else if (config.diskstatus[0] & RAID_DISKSTATUS_MISSING) { 435 (void) printf(gettext("MISSING\n")); 436 } else { 437 (void) printf(gettext("OK\n")); 438 } 439 440 for (i = 1; i < config.ndisks; i++) { 441 (void) printf("\t\t\t\tc%dt%dd0\t\t", c, config.disk[i]); 442 if (config.diskstatus[i] & RAID_DISKSTATUS_FAILED) { 443 (void) printf(gettext("FAILED\n")); 444 } else if (config.diskstatus[i] & RAID_DISKSTATUS_MISSING) { 445 (void) printf(gettext("MISSING\n")); 446 } else { 447 (void) printf(gettext("OK\n")); 448 } 449 } 450 } 451 452 static void 453 print_disklist() 454 { 455 raidlist_t *curr = raids; 456 while (curr != NULL) { 457 print_raidconfig(curr->controller, curr->raid_config); 458 curr = curr->next; 459 } 460 } 461 462 static void 463 free_disklist() 464 { 465 raidlist_t *curr = raids; 466 467 while (curr != NULL) { 468 raidlist_t *temp; 469 temp = curr; 470 curr = curr->next; 471 free(temp); 472 } 473 } 474 475 static void 476 do_search() 477 { 478 DIR *dir; 479 struct dirent *dp; 480 char buf[MAXPATHLEN]; 481 int c; 482 int i, j; 483 484 /* 485 * In case repeated numbers were found, assign the repititions as 486 * RAID_DONT_USE 487 */ 488 for (i = 0; i < ctrl_nums; i++) { 489 int first_one = 1; 490 for (j = 0; j < ctrl_nums; j++) { 491 if (info_ctrl[i][INFO_CTRL] == 492 info_ctrl[j][INFO_CTRL]) { 493 if (info_ctrl[j][INFO_STATUS] == RAID_DONT_USE) 494 continue; 495 if (first_one) { 496 first_one = 0; 497 } else { 498 info_ctrl[j][INFO_STATUS] = 499 RAID_DONT_USE; 500 } 501 } 502 } 503 } 504 505 if ((dir = opendir("/dev/cfg")) == NULL) { 506 (void) fprintf(stderr, 507 gettext("Cannot open /dev/cfg: %s\n"), strerror(errno)); 508 return; 509 } 510 while ((dp = readdir(dir)) != NULL) { 511 if (strcmp(dp->d_name, ".") == 0 || 512 strcmp(dp->d_name, "..") == 0) 513 continue; 514 if (sscanf(dp->d_name, "c%d", &c) != 1) 515 continue; 516 (void) snprintf(buf, sizeof (buf), "/dev/cfg/%s", dp->d_name); 517 add_raid_to_raidlist(buf, c); 518 } 519 (void) closedir(dir); 520 } 521 522 /* 523 * do_info() will do the following: 524 * - create a list of disks' devctls 525 * - try to talk to each of the devctls found 526 * - if raid configuration is found, display it. 527 */ 528 static void 529 do_info() 530 { 531 int i; 532 (void) chdir(DEVDIR); 533 534 do_search(); 535 536 if (raids == NULL) { 537 if (info_ctrl != NULL) { 538 print_no_raids(); 539 for (i = 0; i < ctrl_nums; i++) 540 free(info_ctrl[i]); 541 free(info_ctrl); 542 } else { 543 (void) printf(gettext("No RAID volumes found\n")); 544 } 545 return; 546 } 547 548 print_header(); 549 print_disklist(); 550 print_no_raids(); 551 free_disklist(); 552 if (info_ctrl) { 553 for (i = 0; i < ctrl_nums; i++) 554 free(info_ctrl[i]); 555 free(info_ctrl); 556 } 557 } 558 559 static int 560 disk_there(int c, int t) 561 { 562 char disk[100]; 563 int fd; 564 565 (void) snprintf(disk, sizeof (disk), "c%dt%dd0s2", c, t); 566 567 fd = open(disk, O_RDWR | O_NDELAY); 568 if (fd == -1) { 569 return (-1); 570 } 571 572 (void) close(fd); 573 return (0); 574 } 575 576 static int 577 get_controller(char *dev) 578 { 579 raidlist_t *curr; 580 int c; 581 do_search(); 582 curr = raids; 583 while (curr != NULL) { 584 if (strcmp(curr->devctl, dev) == 0) { 585 c = curr->controller; 586 break; 587 } 588 curr = curr->next; 589 } 590 591 free_disklist(); 592 return (c); 593 } 594 595 static int 596 disk_mounted(char *d) 597 { 598 struct mnttab mt; 599 FILE *f = fopen("/etc/mnttab", "r"); 600 601 while (getmntent(f, &mt) != EOF) 602 if (strstr(mt.mnt_special, d) != NULL) 603 return (1); 604 return (0); 605 } 606 607 static int 608 disk_big_enough(char **d, diskaddr_t *cap, int *errcond) 609 { 610 struct dk_minfo minfo; 611 char disk[N_DISKS][MAXPATHLEN]; 612 diskaddr_t disk_lbsize[N_DISKS]; 613 diskaddr_t disk_capacity[N_DISKS]; 614 int i, fd; 615 616 for (i = 0; i < N_DISKS; i++) { 617 (void) snprintf(disk[i], sizeof (disk[i]), DEVDIR"/%ss2", d[i]); 618 fd = open(disk[i], O_RDWR | O_NDELAY); 619 if (fd == -1) { 620 return (FAILURE); 621 } 622 623 if (ioctl(fd, DKIOCGMEDIAINFO, &minfo) == -1) { 624 (void) close(fd); 625 return (FAILURE); 626 } 627 628 disk_lbsize[i] = minfo.dki_lbsize; 629 disk_capacity[i] = minfo.dki_capacity; 630 (void) close(fd); 631 } 632 633 /* lbsize must be the same on both disks */ 634 if (disk_lbsize[0] != disk_lbsize[1]) { 635 *errcond = 2; 636 return (INVALID_ARG); 637 } 638 639 /* secondary size is not greater than or equal to primary size */ 640 if (disk_capacity[0] > disk_capacity[1]) { 641 *errcond = 1; 642 return (INVALID_ARG); 643 } 644 645 /* Secondary disk is big enough */ 646 *cap = disk_capacity[0]; 647 return (SUCCESS); 648 } 649 650 static int 651 do_config_change_state(cfga_cmd_t cmd, int d, int c) 652 { 653 cfga_err_t cfga_err; 654 char *ap_id; 655 int rv = SUCCESS; 656 int count = 0; 657 658 ap_id = (char *)malloc(100); 659 if (ap_id == NULL) 660 return (FAILURE); 661 662 (void) snprintf(ap_id, 100, "c%d::dsk/c%dt%dd0", c, c, d); 663 664 /* 665 * If the config_change_state() funcation fails, we want to 666 * retry. If the retry fails, then we return failure to fail. 667 * 668 * If we fail: 669 * 670 * If we were called from create, then we fail the raid 671 * creation. 672 * 673 * If we were called from delete, then the disk will not 674 * be re-configured by raidctl. 675 */ 676 do { 677 cfga_err = config_change_state(cmd, 1, &ap_id, NULL, 678 NULL, NULL, NULL, 0); 679 count++; 680 } while (cfga_err != CFGA_OK && count < 2); 681 682 if (cfga_err != CFGA_OK) 683 rv = FAILURE; 684 685 free(ap_id); 686 return (rv); 687 } 688 689 static int 690 do_create(char **d) 691 { 692 raid_config_t config; 693 char disk[N_DISKS][MAXPATHLEN] = {0}; 694 char channel1[MAXPATHLEN]; 695 char channel2[MAXPATHLEN]; 696 diskaddr_t capacity; 697 int fd, fd2, size, errcond, disk_here = 1; 698 int c[N_DISKS]; 699 int t[N_DISKS]; 700 char *tmp; 701 int i; 702 703 (void) chdir(DEVDIR); 704 705 for (i = 0; i < N_DISKS; i++) { 706 if ((sscanf(d[i], "c%dt%dd0", &c[i], &t[i])) != 2 || 707 t[i] < 0) { 708 (void) fprintf(stderr, 709 gettext("Invalid disk format.\n")); 710 return (INVALID_ARG); 711 } 712 (void) snprintf(disk[i], sizeof (disk[i]), DEVDIR"/%ss2", d[i]); 713 } 714 715 /* Must be on same controller */ 716 if (c[0] != c[1]) { 717 (void) fprintf(stderr, 718 gettext("Disks must be on the same controller.\n")); 719 return (INVALID_ARG); 720 } 721 722 /* primary disk target must be lower than secondary disk target */ 723 if (t[0] > t[1]) { 724 (void) fprintf(stderr, gettext("Primary target ID " 725 "must be less than secondary target ID.\n")); 726 return (INVALID_ARG); 727 } 728 729 /* disks must not be the same */ 730 if (t[0] == t[1]) { 731 (void) fprintf(stderr, gettext("Disks must be different.\n")); 732 return (INVALID_ARG); 733 } 734 735 /* disks must be present */ 736 if (disk_there(c[0], t[0])) { 737 (void) printf(gettext("Disk 'c%dt%dd0' is not present.\n"), 738 c[0], t[0]); 739 disk_here = 0; 740 } 741 if (disk_there(c[1], t[1])) { 742 (void) printf(gettext("Disk 'c%dt%dd0' is not present.\n"), 743 c[0], t[1]); 744 disk_here = 0; 745 } 746 747 if (!disk_here) { 748 (void) printf(gettext("Cannot create RAID volume.\n")); 749 return (INVALID_ARG); 750 } 751 752 /* secondary disk's size must be greater or equal to primary disk's */ 753 switch (disk_big_enough(d, &capacity, &errcond)) { 754 case FAILURE: 755 return (FAILURE); 756 case INVALID_ARG: 757 switch (errcond) { 758 case 1: 759 (void) fprintf(stderr, gettext("Cannot create RAID volume when " 760 "primary disk is larger than secondary disk.\n")); 761 break; 762 case 2: 763 (void) fprintf(stderr, gettext("Cannot create RAID volume when " 764 "disk block sizes differ.\n")); 765 } 766 return (INVALID_ARG); 767 } 768 769 /* secondary disk must not be mounted */ 770 if (disk_mounted(d[1])) { 771 (void) fprintf(stderr, gettext("Cannot create RAID volume when " 772 "secondary disk \"%s\" is mounted.\n"), d[1]); 773 return (INVALID_ARG); 774 } 775 776 /* Only one RAID can exist per controller */ 777 if (get_devctl(disk[0], channel1)) 778 return (FAILURE); 779 780 fd = open(channel1, O_RDONLY); 781 if (fd == -1) { 782 perror(channel1); 783 return (FAILURE); 784 } 785 786 if (ioctl(fd, RAID_GETCONFIG, &config) < 0) { 787 raidctl_error("RAID_GETCONFIG"); 788 goto fail1; 789 } 790 791 if (config.ndisks != 0) { 792 (void) printf(gettext("RAID Volume already exists on this " 793 "controller 'c%dt%dd0'\n"), c[0], config.targetid); 794 goto fail1; 795 } 796 797 /* 798 * Make sure there isn't a raid created on this controller's 799 * other channel 800 */ 801 (void) strlcpy(channel2, channel1, sizeof (channel2)); 802 tmp = strrchr(channel2, ':'); 803 tmp[0] = 0; 804 size = strlen(channel2); 805 806 /* 807 * Format the channel string for the other channel so we can 808 * see if a raid exists on it. In this case if we are being asked 809 * to create a raid on channel 2 (indicated by the 1,1 at the end 810 * of the string) we want to check channel 1) otherwise we will 811 * check channel 2. 812 */ 813 if (channel2[size - 2] == ',') { 814 channel2[size - 1] = 0; 815 channel2[size - 2] = 0; 816 (void) snprintf(channel2, sizeof (channel2), "%s:devctl", 817 channel2); 818 } else { 819 (void) snprintf(channel2, sizeof (channel2), "%s,1:devctl", 820 channel2); 821 } 822 823 fd2 = open(channel2, O_RDONLY); 824 if (fd2 == -1) { 825 if (errno == ENOENT) 826 goto no_secondary_channel; 827 perror(channel2); 828 goto fail1; 829 } 830 831 if (ioctl(fd2, RAID_GETCONFIG, &config) < 0) { 832 goto fail2; 833 } 834 835 if (config.ndisks != 0) { 836 int cx; 837 cx = get_controller(channel2); 838 (void) printf(gettext("RAID Volume already exists on this " 839 "controller 'c%dt%dd0'\n"), cx, config.targetid); 840 goto fail2; 841 } 842 843 no_secondary_channel: 844 845 /* No other RAID volumes exist, so we may continue */ 846 config.raid_capacity = capacity; 847 config.raid_level = 1; /* RAID 1: Mirror */ 848 config.targetid = t[0]; /* Assume identity of first disk */ 849 config.disk[0] = t[0]; /* Primary Disk */ 850 config.disk[1] = t[1]; /* Secondary Disk */ 851 852 /* Make secondary disk inaccessible to the system */ 853 if (do_config_change_state(CFGA_CMD_UNCONFIGURE, 854 config.disk[1], c[0])) { 855 perror("config_change_state"); 856 goto fail2; 857 } 858 859 if (ioctl(fd, RAID_CREATE, &config)) { 860 (void) do_config_change_state(CFGA_CMD_CONFIGURE, 861 config.disk[1], c[0]); 862 raidctl_error("RAID_CREATE"); 863 goto fail2; 864 } 865 866 (void) printf(gettext("Volume 'c%dt%dd0' created\n"), c[0], t[0]); 867 (void) close(fd); 868 (void) close(fd2); 869 return (SUCCESS); 870 871 fail2: 872 (void) close(fd2); 873 fail1: 874 (void) close(fd); 875 return (FAILURE); 876 } 877 878 static int 879 do_delete(char *d) 880 { 881 raid_config_t config; 882 char disk1[MAXPATHLEN]; 883 char buf[MAXPATHLEN]; 884 int fd; 885 int target; 886 int ctrl; 887 uint8_t t; 888 889 (void) chdir(DEVDIR); 890 891 if ((sscanf(d, "c%dt%dd0", &ctrl, &target)) != 2) { 892 (void) fprintf(stderr, gettext("Invalid disk format.\n")); 893 return (INVALID_ARG); 894 } 895 t = (uint8_t)target; 896 897 (void) snprintf(disk1, sizeof (disk1), DEVDIR"/%ss2", d); 898 899 if (get_devctl(disk1, buf) != 0) { 900 return (FAILURE); 901 } 902 903 fd = open(buf, O_RDONLY); 904 if (fd == -1) { 905 perror(buf); 906 return (FAILURE); 907 } 908 909 if (ioctl(fd, RAID_GETCONFIG, &config)) { 910 raidctl_error("RAID_GETCONFIG"); 911 goto fail; 912 } 913 914 if (config.ndisks == 0) { 915 (void) fprintf(stderr, gettext("No RAID Volume exists on " 916 "controller '%d'\n"), ctrl); 917 goto fail; 918 } 919 920 if (config.targetid != t) { 921 (void) fprintf(stderr, 922 gettext("RAID volume 'c%dt%dd0' does not exist\n"), 923 ctrl, t); 924 goto fail; 925 } 926 927 if (ioctl(fd, RAID_DELETE, &t)) { 928 perror("RAID_DELETE"); 929 goto fail; 930 } 931 932 /* 933 * Make secondary disk accessible to the system. 934 * Ignore return value from do_config_change_state. 935 */ 936 (void) do_config_change_state(CFGA_CMD_CONFIGURE, config.disk[1], ctrl); 937 938 (void) fprintf(stderr, gettext("Volume 'c%dt%dd0' deleted.\n"), 939 ctrl, target); 940 (void) close(fd); 941 return (SUCCESS); 942 943 fail: 944 (void) close(fd); 945 return (FAILURE); 946 } 947 948 static int 949 getfcodever(uint8_t *rombuf, uint32_t nbytes, char **fcodeversion) 950 { 951 int x, y, size; 952 int found_1 = 0, found_2 = 0; 953 int image_length = 0; 954 int no_of_images = 0; 955 uint8_t *rombuf_1 = NULL; 956 uint16_t image_units = 0; 957 958 /* 959 * Single Image - Open firmware image 960 */ 961 if (rombuf[gw(&rombuf[PCIR_OFF]) + PCIR_CODETYPE] == 1) { 962 rombuf_1 = rombuf + gw(rombuf + PCIR_OFF) + PCI_PDS_INDICATOR; 963 no_of_images = 1; 964 goto process_image; 965 } 966 967 /* 968 * Combined Image - First Image - x86/PC-AT Bios image 969 */ 970 if (rombuf[gw(&rombuf[PCIR_OFF]) + PCIR_CODETYPE] != 0) { 971 (void) fprintf(stderr, gettext("This is neither open image" 972 " nor Bios/Fcode combined image\n")); 973 return (1); 974 } 975 976 /* 977 * Seek to 2nd Image 978 */ 979 rombuf_1 = rombuf + gw(rombuf + PCI_ROM_PCI_DATA_STRUCT_PTR); 980 image_units = gw(rombuf_1 + PCI_PDS_IMAGE_LENGTH); 981 image_length = image_units * PCI_IMAGE_UNIT_SIZE; 982 rombuf_1 += image_length; 983 984 /* 985 * Combined Image - Second Image - Open Firmware image 986 */ 987 if (rombuf_1[PCI_PDS_CODE_TYPE] != 1) { 988 (void) fprintf(stderr, gettext("This is neither open image" 989 " nor Bios/Fcode combined image\n")); 990 return (1); 991 } 992 rombuf_1 += PCI_PDS_INDICATOR; 993 no_of_images = 2; 994 995 process_image: 996 /* 997 * This should be the last image 998 */ 999 if (*rombuf_1 != LAST_IMAGE) { 1000 (void) fprintf(stderr, gettext("This is not a valid " 1001 "Bios/Fcode image file\n")); 1002 return (1); 1003 } 1004 1005 /* 1006 * Scan through the bois/fcode file to get the fcode version 1007 * 0x12 and 0x7 indicate the start of the fcode version string 1008 */ 1009 for (x = 0; x < (nbytes - 8); x++) { 1010 if ((rombuf[x] == FCODE_VERS_KEY1) && 1011 (rombuf[x+1] == FCODE_VERS_KEY2) && 1012 (rombuf[x+2] == 'v') && (rombuf[x+3] == 'e') && 1013 (rombuf[x+4] == 'r') && (rombuf[x+5] == 's') && 1014 (rombuf[x+6] == 'i') && (rombuf[x+7] == 'o') && 1015 (rombuf[x+8] == 'n')) { 1016 found_1 = 1; 1017 break; 1018 } 1019 } 1020 1021 /* 1022 * Store the version string if we have found the beginning of it 1023 */ 1024 if (found_1) { 1025 while (x > 0) { 1026 if (rombuf[--x] == FCODE_VERS_KEY1) { 1027 if (rombuf[x-1] != FCODE_VERS_KEY1) { 1028 x++; 1029 } 1030 break; 1031 } 1032 } 1033 if (x > 0) { 1034 *fcodeversion = (char *)malloc(rombuf[x] + 1); 1035 for (y = 0; y < rombuf[x]; y++) { 1036 (*fcodeversion)[y] = rombuf[x+y+1]; 1037 } 1038 (*fcodeversion)[y] = '\0'; 1039 } else { 1040 found_1 = 0; 1041 } 1042 } 1043 1044 /* 1045 * Scan through the bois/fcode file to get the Bios version 1046 * "@(#)" string indicates the start of the Bios version string 1047 * Append this version string, after already existing fcode version. 1048 */ 1049 if (no_of_images == 2) { 1050 for (x = 0; x < (nbytes - 4); x++) { 1051 if ((rombuf[x] == '@') && (rombuf[x+1] == '(') && 1052 (rombuf[x+2] == '#') && (rombuf[x+3] == ')')) { 1053 found_2 = 1; 1054 break; 1055 } 1056 } 1057 1058 if (found_2) { 1059 x += 4; 1060 (*fcodeversion)[y] = '\n'; 1061 size = y + strlen((char *)(rombuf + x)) + 1062 strlen(BIOS_STR) + 2; 1063 *fcodeversion = (char *)realloc((*fcodeversion), size); 1064 y++; 1065 (*fcodeversion)[y] = '\0'; 1066 (void) strlcat(*fcodeversion, BIOS_STR, size); 1067 (void) strlcat(*fcodeversion, (char *)(rombuf + x), 1068 size); 1069 } 1070 } 1071 1072 return ((found_1 || found_2) ? 0 : 1); 1073 } 1074 1075 static void 1076 getfwver(uint8_t *rombuf, char *fwversion) 1077 { 1078 (void) snprintf(fwversion, 8, "%d.%.2d.%.2d.%.2d", 1079 rombuf[FW_ROM_OFFSET_VERSION + 3], 1080 rombuf[FW_ROM_OFFSET_VERSION + 2], 1081 rombuf[FW_ROM_OFFSET_VERSION + 1], 1082 rombuf[FW_ROM_OFFSET_VERSION + 0]); 1083 } 1084 1085 static int 1086 checkfile(uint8_t *rombuf, uint32_t nbytes, uint32_t chksum, int *imagetype) 1087 { 1088 char *imageversion = NULL; 1089 char *fwversion; 1090 1091 fwversion = (char *)malloc(8); 1092 1093 if (gw(&rombuf[0]) == PCIROM_SIG) { 1094 /* imageversion is malloc(2)'ed in getfcodever() */ 1095 if (getfcodever(rombuf, nbytes, &imageversion) == 0) { 1096 *imagetype = FCODE_IMAGE; 1097 } else { 1098 *imagetype = UNKNOWN_IMAGE; 1099 } 1100 if (*imagetype != UNKNOWN_IMAGE) { 1101 (void) printf(gettext("Image file contains:\n%s\n"), 1102 imageversion); 1103 free(imageversion); 1104 } else { 1105 if (imageversion != NULL) { 1106 free(imageversion); 1107 } 1108 return (-1); 1109 } 1110 } else if (gw(&rombuf[3]) == FW_ROM_ID) { 1111 if (chksum != 0) { 1112 (void) fprintf(stderr, 1113 gettext("The ROM checksum appears bad " 1114 "(%d)\n"), chksum); 1115 return (-1); 1116 } 1117 getfwver(rombuf, fwversion); 1118 1119 if ((gw(&rombuf[FW_ROM_OFFSET_CHIP_TYPE]) & 1120 MPI_FW_HEADER_PID_PROD_MASK) == 1121 MPI_FW_HEADER_PID_PROD_IM_SCSI) { 1122 (void) printf(gettext("ROM image contains " 1123 "MPT firmware version %s " 1124 "(w/Integrated Mirroring)\n"), 1125 fwversion); 1126 } else { 1127 (void) printf(gettext("ROM image contains " 1128 "MPT firmware ""version %s\n"), 1129 fwversion); 1130 } 1131 free(fwversion); 1132 } else { 1133 1134 #ifdef DEBUG 1135 (void) fprintf(stderr, "Not valid FCODE image %x\n", gw(&rombuf[0])); 1136 #else 1137 (void) fprintf(stderr, gettext("Not valid FCODE image\n")); 1138 #endif 1139 return (-1); 1140 } 1141 return (0); 1142 } 1143 1144 static int 1145 updateflash(uint8_t *rombuf, uint32_t nbytes, char *devctl) 1146 { 1147 int fd = 0; 1148 update_flash_t flashdata; 1149 1150 fd = open(devctl, O_RDONLY); 1151 if (fd == -1) { 1152 perror(devctl); 1153 return (-1); 1154 } 1155 (void) memset(&flashdata, 0, sizeof (flashdata)); 1156 flashdata.ptrbuffer = (caddr_t)rombuf; 1157 flashdata.size = nbytes; 1158 if ((rombuf[0] == 0x55) && (rombuf[1] == 0xaa)) { 1159 flashdata.type = FW_TYPE_FCODE; 1160 } else { 1161 flashdata.type = FW_TYPE_UCODE; 1162 } 1163 1164 if (ioctl(fd, RAID_UPDATEFW, &flashdata)) { 1165 raidctl_error("RAID_UPDATEFW"); 1166 (void) close(fd); 1167 return (-1); 1168 } 1169 1170 (void) close(fd); 1171 return (0); 1172 } 1173 1174 static int 1175 readfile(char *filespec, uint8_t **rombuf, uint32_t *nbytes, uint32_t *chksum) 1176 { 1177 struct stat statbuf; 1178 uint32_t count; 1179 uint32_t checksum = 0; 1180 int fd, i; 1181 uint8_t *filebuf; 1182 1183 1184 if ((fd = open((const char *)filespec, O_RDONLY | O_NDELAY)) == -1) { 1185 perror(filespec); 1186 return (-1); 1187 } 1188 1189 if (fstat(fd, &statbuf) != 0) { 1190 perror("fstat"); 1191 (void) fprintf(stderr, 1192 gettext("Error getting stats on file\n")); 1193 (void) close(fd); 1194 return (-1); 1195 } 1196 1197 #ifdef DEBUG 1198 (void) printf("Filesize = %ld\n", statbuf.st_size); 1199 #endif 1200 1201 filebuf = (uint8_t *)realloc(*rombuf, statbuf.st_size + *nbytes); 1202 1203 count = read(fd, filebuf + *nbytes, statbuf.st_size); 1204 (void) close(fd); 1205 if (count != statbuf.st_size) { 1206 perror("size check"); 1207 (void) fprintf(stderr, gettext("File is corrupt\n")); 1208 return (-1); 1209 } 1210 1211 for (i = 0; i < *nbytes; i++) 1212 checksum += filebuf[i] << (8 * (i & 3)); 1213 1214 *rombuf = filebuf; 1215 *nbytes = *nbytes + count; 1216 *chksum = checksum; 1217 1218 return (0); 1219 } 1220 1221 static int 1222 yes(int c) 1223 { 1224 int i, b; 1225 char ans[SCHAR_MAX + 1]; 1226 1227 for (i = 0; ; i++) { 1228 b = getchar(); 1229 if (b == '\n' || b == '\0' || b == EOF) { 1230 ans[i] = 0; 1231 break; 1232 } 1233 if (i < SCHAR_MAX) 1234 ans[i] = b; 1235 } 1236 if (i >= SCHAR_MAX) { 1237 i = SCHAR_MAX; 1238 ans[SCHAR_MAX] = 0; 1239 } 1240 if ((i != 0) && ((strncmp(yeschr, ans, i)) == 0)) { 1241 return (1); 1242 } else { 1243 (void) fprintf(stderr, gettext("User response is \"%s\", " 1244 "Controller %d not flashed.\n\n"), ans, c); 1245 return (0); 1246 } 1247 } 1248 1249 static int 1250 do_flash(int c, char *fpath, int force) 1251 { 1252 char devctl[MAXPATHLEN] = {0}; 1253 char buf[MAXPATHLEN] = {0}; 1254 int rv = 0; 1255 int imagetype; 1256 uint32_t nbytes = 0; 1257 uint32_t chksum; 1258 uint8_t *rombuf = NULL; 1259 char cwd[MAXPATHLEN]; 1260 1261 /* 1262 * Read fw file 1263 */ 1264 rv = readfile(fpath, &rombuf, &nbytes, &chksum); 1265 if (rv != 0) { 1266 return (FAILURE); 1267 } 1268 1269 (void) getcwd(cwd, sizeof (cwd)); 1270 1271 (void) chdir(DEVDIR); 1272 1273 /* Get link from "/dev/cfg" */ 1274 (void) snprintf(buf, sizeof (buf), "/dev/cfg/c%d", c); 1275 if (get_link_path(buf, devctl) != 0) { 1276 (void) fprintf(stderr, 1277 gettext("Invalid controller '%d'\n"), c); 1278 return (INVALID_ARG); 1279 } 1280 1281 /* Check File */ 1282 rv = checkfile(rombuf, nbytes, chksum, &imagetype); 1283 if (rv != 0) { 1284 return (FAILURE); 1285 } 1286 1287 /* Confirm */ 1288 if (!force) { 1289 (void) fprintf(stderr, gettext("Update flash image on " 1290 "controller %d (%s/%s)? "), c, yeschr, nochr); 1291 if (!yes(c)) { 1292 return (SUCCESS); 1293 } 1294 } 1295 1296 /* Do Flash */ 1297 if (updateflash(rombuf, nbytes, devctl)) { 1298 (void) fprintf(stderr, gettext("Flash not updated on " 1299 "Controller %d.\n\n"), c); 1300 return (INVALID_ARG); 1301 } 1302 (void) printf(gettext("Flash updated successfully.\n\n")); 1303 return (SUCCESS); 1304 } 1305 1306 static int 1307 fully_numeric(char *str) 1308 { 1309 int size = strlen(str); 1310 int i; 1311 1312 for (i = 0; i < size; i++) { 1313 if (i == 0 && str[i] == '-' && size != 1) 1314 continue; 1315 if (!isdigit(str[i])) 1316 return (0); 1317 } 1318 return (1); 1319 } 1320 1321 /* 1322 * Useful parsing macros 1323 */ 1324 #define must_be(s, c) if (*s++ != c) return (0) 1325 #define skip_digits(s) while (isdigit(*s)) s++ 1326 1327 /* 1328 * Return true if a name is in the internal canonical form 1329 */ 1330 static int 1331 canonical_name(char *name) 1332 { 1333 must_be(name, 'c'); 1334 skip_digits(name); 1335 if (*name == 't') { 1336 name++; 1337 skip_digits(name); 1338 } 1339 must_be(name, 'd'); 1340 skip_digits(name); 1341 return (*name == 0); 1342 } 1343 1344 int 1345 main(int argc, char **argv) 1346 { 1347 int rv = SUCCESS; 1348 int i, c; 1349 int findex = DO_HW_RAID_INFO; 1350 int controller; 1351 char *disks[N_DISKS]; 1352 char *darg; 1353 char *farg; 1354 char *progname; 1355 1356 int l_flag = 0; 1357 int c_flag = 0; 1358 int d_flag = 0; 1359 int f_flag = 0; 1360 int F_flag = 0; 1361 int no_flags = 1; 1362 char *current_dir; 1363 1364 (void) setlocale(LC_ALL, ""); 1365 (void) textdomain(TEXT_DOMAIN); 1366 1367 if (geteuid() != 0) { 1368 (void) fprintf(stderr, gettext("Must be root.\n")); 1369 exit(1); 1370 } 1371 1372 if ((progname = strrchr(argv[0], '/')) == NULL) 1373 progname = argv[0]; 1374 else 1375 progname++; 1376 1377 raids = NULL; 1378 1379 (void) strncpy(yeschr, nl_langinfo(YESSTR), SCHAR_MAX + 1); 1380 (void) strncpy(nochr, nl_langinfo(NOSTR), SCHAR_MAX + 1); 1381 1382 while ((c = getopt(argc, argv, "clfd:F:")) != EOF) { 1383 switch (c) { 1384 case 'c': 1385 if (f_flag || argc != 4) { 1386 usage(progname); 1387 } 1388 1389 findex = DO_HW_RAID_CREATE; 1390 c_flag = 1; 1391 no_flags = 0; 1392 break; 1393 case 'd': 1394 darg = optarg; 1395 d_flag = 1; 1396 findex = DO_HW_RAID_DELETE; 1397 no_flags = 0; 1398 break; 1399 case 'l': 1400 findex = DO_HW_RAID_INFO; 1401 l_flag = 1; 1402 no_flags = 0; 1403 break; 1404 case 'F': 1405 findex = DO_HW_RAID_FLASH; 1406 farg = optarg; 1407 F_flag = 1; 1408 no_flags = 0; 1409 break; 1410 case 'f': 1411 f_flag = 1; 1412 no_flags = 0; 1413 break; 1414 case '?': default: 1415 usage(progname); 1416 } 1417 } 1418 1419 if (no_flags && argc > 1) 1420 usage(progname); 1421 1422 /* compatibility rules */ 1423 if (c_flag && d_flag) 1424 usage(progname); 1425 if (l_flag && (d_flag || c_flag || f_flag || F_flag)) 1426 usage(progname); 1427 if (F_flag && (d_flag || c_flag || l_flag)) 1428 usage(progname); 1429 1430 switch (findex) { 1431 case DO_HW_RAID_INFO: 1432 if (l_flag) { 1433 /* 1434 * "raidctl" makes argc == 1 1435 * "-l" makes argc == 2 1436 */ 1437 ctrl_nums = argc - 2; 1438 if (ctrl_nums != 0) { 1439 info_ctrl = (int **) 1440 malloc(ctrl_nums * sizeof (int)); 1441 if (info_ctrl == NULL) 1442 return (FAILURE); 1443 } 1444 for (i = 0; i < ctrl_nums; i++) { 1445 char *tmp = argv[i + 2]; 1446 1447 info_ctrl[i] = (int *)malloc(2 * sizeof (int)); 1448 if (info_ctrl[i] == NULL) { 1449 free(info_ctrl); 1450 return (FAILURE); 1451 } 1452 if (fully_numeric(tmp)) { 1453 (void) sscanf(tmp, "%d", 1454 &info_ctrl[i][INFO_CTRL]); 1455 info_ctrl[i][INFO_STATUS] = 1456 RAID_INVALID_CTRL; 1457 } else { 1458 (void) fprintf(stderr, 1459 gettext("Invalid controller '%s'\n"), 1460 tmp); 1461 info_ctrl[i][INFO_STATUS] = 1462 RAID_DONT_USE; 1463 } 1464 } 1465 } else if (argc > 1) { 1466 usage(progname); 1467 } 1468 1469 do_info(); 1470 break; 1471 case DO_HW_RAID_CREATE: 1472 for (i = 0; i < N_DISKS; i++) { 1473 disks[i] = argv[argc - 2 + i]; 1474 if (!canonical_name(disks[i])) 1475 usage(progname); 1476 } 1477 rv = do_create(disks); 1478 break; 1479 case DO_HW_RAID_DELETE: 1480 if (!canonical_name(darg)) 1481 usage(progname); 1482 1483 rv = do_delete(darg); 1484 break; 1485 case DO_HW_RAID_FLASH: 1486 /* 1487 * "raidctl" makes argc == 1 1488 * "-F" makes argc == 2 1489 * "filename" makes argc == 3 1490 * "-f" makes argc == 4 if added. 1491 */ 1492 ctrl_nums = argc - f_flag - 3; 1493 if (ctrl_nums == 0) 1494 usage(progname); 1495 1496 current_dir = getcwd(NULL, MAXPATHLEN); 1497 1498 for (i = 0; i < ctrl_nums; i++) { 1499 char *tmp = argv[i + 3 + f_flag]; 1500 (void) chdir(current_dir); 1501 if (fully_numeric(tmp)) { 1502 (void) sscanf(tmp, "%d", &controller); 1503 rv = do_flash(controller, farg, f_flag); 1504 if (rv == FAILURE) 1505 break; 1506 } else { 1507 (void) fprintf(stderr, 1508 gettext("Invalid controller '%s'\n"), 1509 tmp); 1510 } 1511 } 1512 free(current_dir); 1513 break; 1514 default: 1515 usage(progname); 1516 } 1517 return (rv); 1518 } 1519