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