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