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