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