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