xref: /titanic_50/usr/src/cmd/stmsboot/stmsboot_util.c (revision 4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
580ab886dSwesolows  * Common Development and Distribution License (the "License").
680ab886dSwesolows  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
2180ab886dSwesolows 
227c478bd9Sstevel@tonic-gate /*
23ed141cfcSsrivijitha dugganapalli  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate #include <stdio.h>
287c478bd9Sstevel@tonic-gate #include <stdlib.h>
297c478bd9Sstevel@tonic-gate #include <stdarg.h>
307c478bd9Sstevel@tonic-gate #include <sys/types.h>
317c478bd9Sstevel@tonic-gate #include <sys/stat.h>
327c478bd9Sstevel@tonic-gate #include <fcntl.h>
337c478bd9Sstevel@tonic-gate #include <errno.h>
347c478bd9Sstevel@tonic-gate #include <unistd.h>
357c478bd9Sstevel@tonic-gate #include <stropts.h>
367c478bd9Sstevel@tonic-gate #include <strings.h>
377c478bd9Sstevel@tonic-gate #include <sys/param.h>
387c478bd9Sstevel@tonic-gate #include <libdevinfo.h>
397c478bd9Sstevel@tonic-gate #include <locale.h>
407c478bd9Sstevel@tonic-gate #include <libintl.h>
417c478bd9Sstevel@tonic-gate #include <devid.h>
42ed141cfcSsrivijitha dugganapalli #include <sys/libdevid.h>
43a0261a43SJames C. McPherson #include <sys/modctl.h> /* for MAXMODCONFNAME */
44a0261a43SJames C. McPherson #include <sys/scsi/adapters/scsi_vhci.h>
457c478bd9Sstevel@tonic-gate 
467c478bd9Sstevel@tonic-gate /*
47a0261a43SJames C. McPherson  * SAVE_DIR is the directory in which system files are saved.
48a0261a43SJames C. McPherson  * SAVE_DIR must be under the root filesystem, as this program is
497c478bd9Sstevel@tonic-gate  * typically run before any other filesystems are mounted.
507c478bd9Sstevel@tonic-gate  */
517c478bd9Sstevel@tonic-gate #define	SAVE_DIR	"/etc/mpxio"
52a0261a43SJames C. McPherson #define	VHCI_CTL_NODE	"/devices/scsi_vhci:devctl"
537c478bd9Sstevel@tonic-gate 
54a0261a43SJames C. McPherson /* nvlist property names, these are ALL string types */
55a0261a43SJames C. McPherson #define	NVL_DEVID 	"nvl-devid"
56a0261a43SJames C. McPherson #define	NVL_PATH 	"nvl-path"
57a0261a43SJames C. McPherson #define	NVL_PHYSPATH	"nvl-physpath"
58a0261a43SJames C. McPherson #define	NVL_MPXPATH	"nvl-mpxiopath"
59a0261a43SJames C. McPherson #define	NVL_MPXEN	"nvl-mpxioenabled"
607c478bd9Sstevel@tonic-gate 
61a0261a43SJames C. McPherson #define	MPX_LIST		0x01
62a0261a43SJames C. McPherson #define	MPX_MAP			0x02
63a0261a43SJames C. McPherson #define	MPX_CAPABLE_CTRL	0x04
64a0261a43SJames C. McPherson #define	MPX_INIT		0x08
65a0261a43SJames C. McPherson #define	MPX_PHYSICAL		0x10
66a0261a43SJames C. McPherson #define	MPX_BOOTPATH		0x20
67a0261a43SJames C. McPherson #define	MPX_UPDATEVFSTAB	0x40
68a0261a43SJames C. McPherson #define	MPX_USAGE		0x80
69a0261a43SJames C. McPherson #define	MSG_INFO		0x01
70a0261a43SJames C. McPherson #define	MSG_ERROR		0x02
71a0261a43SJames C. McPherson #define	MSG_PANIC		0x04
7260fffc19Sjw149990 
73a0261a43SJames C. McPherson #define	BOOT			0x01
74a0261a43SJames C. McPherson #define	NONBOOT			0x00
757c478bd9Sstevel@tonic-gate 
767c478bd9Sstevel@tonic-gate static di_node_t devinfo_root = DI_NODE_NIL;
77a0261a43SJames C. McPherson static char *ondiskname = "/etc/mpxio/devid_path.cache";
787c478bd9Sstevel@tonic-gate 
797c478bd9Sstevel@tonic-gate /*
80a0261a43SJames C. McPherson  * We use devid-keyed nvlists to keep track of the guid, traditional and
81a0261a43SJames C. McPherson  * MPxIO-enabled /dev/rdsk paths. Each of these nvlists is eventually
82a0261a43SJames C. McPherson  * added to our global nvlist and our on-disk nvlist.
837c478bd9Sstevel@tonic-gate  */
84a0261a43SJames C. McPherson static nvlist_t *mapnvl;
85a0261a43SJames C. McPherson static int mpxenabled = 0;
86a0261a43SJames C. McPherson static int limctrl = -1;
8735c62094Sjianfei wang - Sun Microsystems - Beijing China static int mpxprop = 0;
88a0261a43SJames C. McPherson static int guid = 0;
89a0261a43SJames C. McPherson static char *drvlimit;
90a0261a43SJames C. McPherson static int globarg = 0;
91a0261a43SJames C. McPherson static int debugflag = 0;
92a0261a43SJames C. McPherson static char *devicep;
93a0261a43SJames C. McPherson static int readonlyroot = 0;
94a0261a43SJames C. McPherson static int cap_N_option = 0;
95a0261a43SJames C. McPherson 
96a0261a43SJames C. McPherson static void print_mpx_capable(di_node_t curnode);
97a0261a43SJames C. McPherson static int popcheck_devnvl(di_node_t thisnode, nvlist_t *devnvl,
98a0261a43SJames C. McPherson     char *strdevid);
99a0261a43SJames C. McPherson static int mpxio_nvl_boilerplate(di_node_t curnode);
100a0261a43SJames C. McPherson static int validate_devnvl();
101a0261a43SJames C. McPherson static void report_map(char *argdev, int physpath);
102a0261a43SJames C. McPherson static void list_devs(int listguids, int ctrl);
103a0261a43SJames C. McPherson static void logmsg(int level, const char *msg, ...);
104a0261a43SJames C. McPherson static char *find_link(di_node_t cnode);
105a0261a43SJames C. McPherson static void usage();
106a0261a43SJames C. McPherson static void parse_args(int argc, char *argv[]);
107a0261a43SJames C. McPherson static void get_devid(di_node_t node, ddi_devid_t *thisdevid);
108a0261a43SJames C. McPherson static int print_bootpath();
109a0261a43SJames C. McPherson static void vhci_to_phci(char *devpath, char *physpath);
110a0261a43SJames C. McPherson static int update_vfstab();
111a0261a43SJames C. McPherson 
112a0261a43SJames C. McPherson int
113a0261a43SJames C. McPherson main(int argc, char **argv)
1147c478bd9Sstevel@tonic-gate {
115a0261a43SJames C. McPherson 	struct stat cachestat;
116a0261a43SJames C. McPherson 	int mapfd = 0;
117a0261a43SJames C. McPherson 	int rv = 0;
118a0261a43SJames C. McPherson 	char *ondiskbuf;
119a0261a43SJames C. McPherson 	size_t newsz = 0;
1207c478bd9Sstevel@tonic-gate 
121a0261a43SJames C. McPherson 	parse_args(argc, argv);
122a0261a43SJames C. McPherson 	errno = 0;
123a0261a43SJames C. McPherson 	devinfo_root = di_init("/", DINFOCPYALL|DINFOFORCE);
124a0261a43SJames C. McPherson 	logmsg(MSG_INFO, "errno = %d after "
125a0261a43SJames C. McPherson 	    "di_init(/,DINFOCPYALL|DINFOFORCE)\n", errno);
126a0261a43SJames C. McPherson 	if (devinfo_root == NULL) {
127a0261a43SJames C. McPherson 		logmsg(MSG_ERROR,
128a0261a43SJames C. McPherson 		    gettext("Unable to take device tree snapshot "
129a0261a43SJames C. McPherson 		    "(%s: %d)\n"), strerror(errno), errno);
130a0261a43SJames C. McPherson 		return (-1);
131a0261a43SJames C. McPherson 	}
132a0261a43SJames C. McPherson 	logmsg(MSG_INFO, "opened root di_node\n");
1337c478bd9Sstevel@tonic-gate 
134a0261a43SJames C. McPherson 	if (globarg == MPX_CAPABLE_CTRL) {
135a0261a43SJames C. McPherson 		/* we just want to find MPxIO-capable controllers and exit */
136a0261a43SJames C. McPherson 		if (drvlimit != NULL) {
137a0261a43SJames C. McPherson 			print_mpx_capable(di_drv_first_node(drvlimit,
138a0261a43SJames C. McPherson 			    devinfo_root));
139a0261a43SJames C. McPherson 		} else {
140a0261a43SJames C. McPherson 			print_mpx_capable(di_drv_first_node("fp",
141a0261a43SJames C. McPherson 			    devinfo_root));
142a0261a43SJames C. McPherson 			print_mpx_capable(di_drv_first_node("mpt",
143a0261a43SJames C. McPherson 			    devinfo_root));
1445b504601Sjiang wu - Sun Microsystems - Beijing China 			print_mpx_capable(di_drv_first_node("mpt_sas",
1455b504601Sjiang wu - Sun Microsystems - Beijing China 			    devinfo_root));
146*4c06356bSdh142964 			print_mpx_capable(di_drv_first_node("pmcs",
147*4c06356bSdh142964 			    devinfo_root));
148a0261a43SJames C. McPherson 		}
149a0261a43SJames C. McPherson 		di_fini(devinfo_root);
150a0261a43SJames C. McPherson 		return (0);
151a0261a43SJames C. McPherson 	}
152a0261a43SJames C. McPherson 
153a0261a43SJames C. McPherson 	mapfd = open(ondiskname, O_RDWR|O_CREAT|O_SYNC, S_IRUSR | S_IWUSR);
154a0261a43SJames C. McPherson 	if (mapfd < 0) {
155a0261a43SJames C. McPherson 		/* we could be in single-user, so try for RO */
156a0261a43SJames C. McPherson 		if ((mapfd = open(ondiskname, O_RDONLY)) < 0) {
157a0261a43SJames C. McPherson 			logmsg(MSG_ERROR,
158a0261a43SJames C. McPherson 			    gettext("Unable to open or create %s:%s\n"),
159a0261a43SJames C. McPherson 			    ondiskname, strerror(errno));
160a0261a43SJames C. McPherson 			return (errno);
161a0261a43SJames C. McPherson 		}
162a0261a43SJames C. McPherson 		readonlyroot = 1;
163a0261a43SJames C. McPherson 	}
164a0261a43SJames C. McPherson 
165a0261a43SJames C. McPherson 	if (stat(ondiskname, &cachestat) != 0) {
166a0261a43SJames C. McPherson 		logmsg(MSG_ERROR,
167a0261a43SJames C. McPherson 		    gettext("Unable to stat() %s: %s\n"),
168a0261a43SJames C. McPherson 		    ondiskname, strerror(errno));
169a0261a43SJames C. McPherson 		return (errno);
170a0261a43SJames C. McPherson 	}
171a0261a43SJames C. McPherson 	ondiskbuf = calloc(1, cachestat.st_size);
172a0261a43SJames C. McPherson 	if (ondiskbuf == NULL) {
173a0261a43SJames C. McPherson 		logmsg(MSG_ERROR,
174a0261a43SJames C. McPherson 		    gettext("Unable to allocate memory for the devid "
175a0261a43SJames C. McPherson 		    "cache file: %s\n"), strerror(errno));
176a0261a43SJames C. McPherson 		return (errno);
177a0261a43SJames C. McPherson 	}
178a0261a43SJames C. McPherson 	rv = read(mapfd, ondiskbuf, cachestat.st_size);
179a0261a43SJames C. McPherson 	if (rv != cachestat.st_size) {
180a0261a43SJames C. McPherson 		logmsg(MSG_ERROR,
181a0261a43SJames C. McPherson 		    gettext("Unable to read all of devid cache file (got %d "
182a0261a43SJames C. McPherson 		    "from expected %d bytes): %s\n"),
183a0261a43SJames C. McPherson 		    rv, cachestat.st_size, strerror(errno));
184a0261a43SJames C. McPherson 		return (errno);
185a0261a43SJames C. McPherson 	}
186a0261a43SJames C. McPherson 	errno = 0;
187a0261a43SJames C. McPherson 	rv = nvlist_unpack(ondiskbuf, cachestat.st_size, &mapnvl, 0);
188a0261a43SJames C. McPherson 	if (rv) {
189a0261a43SJames C. McPherson 		logmsg(MSG_INFO,
190a0261a43SJames C. McPherson 		    "Unable to unpack devid cache file %s: %s (%d)\n",
191a0261a43SJames C. McPherson 		    ondiskname, strerror(rv), rv);
192a0261a43SJames C. McPherson 		if (nvlist_alloc(&mapnvl, NV_UNIQUE_NAME, 0) != 0) {
193a0261a43SJames C. McPherson 			logmsg(MSG_ERROR,
194a0261a43SJames C. McPherson 			    gettext("Unable to allocate root property"
195a0261a43SJames C. McPherson 			    "list\n"));
196a0261a43SJames C. McPherson 			return (errno);
197a0261a43SJames C. McPherson 		}
198a0261a43SJames C. McPherson 	}
199a0261a43SJames C. McPherson 	free(ondiskbuf);
200a0261a43SJames C. McPherson 
201a0261a43SJames C. McPherson 	if (validate_devnvl() < 0) {
202a0261a43SJames C. McPherson 		logmsg(MSG_ERROR,
203a0261a43SJames C. McPherson 		    gettext("unable to validate kernel with on-disk devid "
204a0261a43SJames C. McPherson 		    "cache file\n"));
205a0261a43SJames C. McPherson 		return (errno);
2067c478bd9Sstevel@tonic-gate 	}
2077c478bd9Sstevel@tonic-gate 
2087c478bd9Sstevel@tonic-gate 	/*
209a0261a43SJames C. McPherson 	 * If we're in single-user mode or maintenance mode, we won't
210a0261a43SJames C. McPherson 	 * necessarily have a writable root device (ZFSroot; ufs root is
211a0261a43SJames C. McPherson 	 * different in that we _do_ have a writable root device.
212a0261a43SJames C. McPherson 	 * This causes problems for the devlink calls (see
213a0261a43SJames C. McPherson 	 * $SRC/lib/libdevinfo/devinfo_devlink.c) and we do not try to
214a0261a43SJames C. McPherson 	 * write out the devnvl if root is readonly.
2157c478bd9Sstevel@tonic-gate 	 */
216a0261a43SJames C. McPherson 	if (!readonlyroot) {
217a0261a43SJames C. McPherson 		rv = nvlist_size(mapnvl, &newsz, NV_ENCODE_NATIVE);
218a0261a43SJames C. McPherson 		if (rv) {
219a0261a43SJames C. McPherson 			logmsg(MSG_ERROR,
220a0261a43SJames C. McPherson 			    gettext("Unable to determine size of packed "
221a0261a43SJames C. McPherson 			    "on-disk devid cache file %s: %s (%d).\n"),
222a0261a43SJames C. McPherson 			    ondiskname, strerror(rv), rv);
223a0261a43SJames C. McPherson 			logmsg(MSG_ERROR, gettext("Terminating\n"));
224a0261a43SJames C. McPherson 			nvlist_free(mapnvl);
225a0261a43SJames C. McPherson 			(void) close(mapfd);
226a0261a43SJames C. McPherson 			return (rv);
227a0261a43SJames C. McPherson 		}
228a0261a43SJames C. McPherson 
229a0261a43SJames C. McPherson 		if ((ondiskbuf = calloc(1, newsz)) == NULL) {
230a0261a43SJames C. McPherson 			logmsg(MSG_ERROR,
231a0261a43SJames C. McPherson 			    "Unable to allocate space for writing out new "
232a0261a43SJames C. McPherson 			    "on-disk devid cache file: %s\n", strerror(errno));
233a0261a43SJames C. McPherson 			(void) close(mapfd);
234a0261a43SJames C. McPherson 			nvlist_free(mapnvl);
235a0261a43SJames C. McPherson 			return (errno);
236a0261a43SJames C. McPherson 		}
237a0261a43SJames C. McPherson 
238a0261a43SJames C. McPherson 		rv = nvlist_pack(mapnvl, &ondiskbuf, &newsz,
239a0261a43SJames C. McPherson 		    NV_ENCODE_NATIVE, 0);
240a0261a43SJames C. McPherson 		if (rv) {
241a0261a43SJames C. McPherson 			logmsg(MSG_ERROR,
242a0261a43SJames C. McPherson 			    gettext("Unable to pack on-disk devid cache "
243a0261a43SJames C. McPherson 			    "file: %s (%d)\n"), strerror(rv), rv);
244a0261a43SJames C. McPherson 			(void) close(mapfd);
245a0261a43SJames C. McPherson 			free(ondiskbuf);
246a0261a43SJames C. McPherson 			nvlist_free(mapnvl);
247a0261a43SJames C. McPherson 			return (rv);
248a0261a43SJames C. McPherson 		}
249a0261a43SJames C. McPherson 
250a0261a43SJames C. McPherson 		rv = lseek(mapfd, 0, 0);
251a0261a43SJames C. McPherson 		if (rv == -1) {
252a0261a43SJames C. McPherson 			logmsg(MSG_ERROR,
253a0261a43SJames C. McPherson 			    gettext("Unable to seek to start of devid cache "
254a0261a43SJames C. McPherson 			    "file: %s (%d)\n"), strerror(errno), errno);
255a0261a43SJames C. McPherson 			(void) close(mapfd);
256a0261a43SJames C. McPherson 			free(ondiskbuf);
257a0261a43SJames C. McPherson 			nvlist_free(mapnvl);
258a0261a43SJames C. McPherson 			return (-1);
259a0261a43SJames C. McPherson 		}
260a0261a43SJames C. McPherson 
261a0261a43SJames C. McPherson 		if (write(mapfd, ondiskbuf, newsz) != newsz) {
262a0261a43SJames C. McPherson 			logmsg(MSG_ERROR,
263a0261a43SJames C. McPherson 			    gettext("Unable to completely write out "
264a0261a43SJames C. McPherson 			    "on-disk devid cache file: %s\n"), strerror(errno));
265a0261a43SJames C. McPherson 			(void) close(mapfd);
266a0261a43SJames C. McPherson 			nvlist_free(mapnvl);
267a0261a43SJames C. McPherson 			free(ondiskbuf);
268a0261a43SJames C. McPherson 			return (errno);
269a0261a43SJames C. McPherson 		}
270a0261a43SJames C. McPherson 	} /* !readonlyroot */
271a0261a43SJames C. McPherson 
272a0261a43SJames C. McPherson 	/* Now we can process the command line args */
273a0261a43SJames C. McPherson 	if (globarg == MPX_PHYSICAL) {
274a0261a43SJames C. McPherson 		report_map(devicep, BOOT);
275a0261a43SJames C. McPherson 	} else if (globarg == MPX_BOOTPATH) {
276a0261a43SJames C. McPherson 		rv = print_bootpath();
277a0261a43SJames C. McPherson 		di_fini(devinfo_root);
278a0261a43SJames C. McPherson 		return (rv);
279a0261a43SJames C. McPherson 	} else if (globarg == MPX_UPDATEVFSTAB) {
280a0261a43SJames C. McPherson 		rv = update_vfstab();
281a0261a43SJames C. McPherson 		di_fini(devinfo_root);
282a0261a43SJames C. McPherson 		return (rv);
283a0261a43SJames C. McPherson 	} else if (globarg != MPX_INIT) {
284a0261a43SJames C. McPherson 		if (globarg & MPX_LIST)
285a0261a43SJames C. McPherson 			list_devs(guid, limctrl);
286a0261a43SJames C. McPherson 
287a0261a43SJames C. McPherson 		if (globarg == MPX_MAP)
288a0261a43SJames C. McPherson 			report_map(devicep, NONBOOT);
289a0261a43SJames C. McPherson 	} else {
290a0261a43SJames C. McPherson 		logmsg(MSG_INFO, "\nprivate devid cache file initialised\n");
291a0261a43SJames C. McPherson 	}
292a0261a43SJames C. McPherson 
293a0261a43SJames C. McPherson 	nvlist_free(mapnvl);
294a0261a43SJames C. McPherson 	di_fini(devinfo_root);
295a0261a43SJames C. McPherson 	return (0);
296a0261a43SJames C. McPherson }
297a0261a43SJames C. McPherson 
298a0261a43SJames C. McPherson static void
299a0261a43SJames C. McPherson usage()
300a0261a43SJames C. McPherson {
301a0261a43SJames C. McPherson 	(void) fprintf(stderr,
302a0261a43SJames C. McPherson 	    gettext("usage: stmsboot_util -b | -m devname | "
303a0261a43SJames C. McPherson 	    "-l <ctrl> | -L | [-g] | -n | -N | -i | -p devname\n"));
304a0261a43SJames C. McPherson 	(void) fprintf(stderr, "\n\n");
305a0261a43SJames C. McPherson 	(void) fprintf(stderr, gettext("\t-h\tprint this usage message\n"));
306a0261a43SJames C. McPherson 	(void) fprintf(stderr, gettext("\t-b\tretrieve the system's bootpath "
307a0261a43SJames C. McPherson 	    "setting\n"));
308a0261a43SJames C. McPherson 	(void) fprintf(stderr, gettext("\t-m devname\n"));
309a0261a43SJames C. McPherson 	(void) fprintf(stderr, gettext("\t\tReports the current mapping for "
310a0261a43SJames C. McPherson 	    "devname\n"));
311a0261a43SJames C. McPherson 	(void) fprintf(stderr, gettext("\t-g\tprint the GUID for MPxIO-capable "
312a0261a43SJames C. McPherson 	    "devices. This\n"));
313a0261a43SJames C. McPherson 	(void) fprintf(stderr, gettext("\t\toption is only valid with the -L "
314a0261a43SJames C. McPherson 	    "or -l options\n"));
315a0261a43SJames C. McPherson 	(void) fprintf(stderr, gettext("\t-L | -l <ctrl>\n"));
316a0261a43SJames C. McPherson 	(void) fprintf(stderr, gettext("\t\tList the 'native' to 'MPxIO' "
317a0261a43SJames C. McPherson 	    "device mappings. If <ctrl>\n"));
318a0261a43SJames C. McPherson 	(void) fprintf(stderr, gettext("\t\tis specified, only print mappings "
319a0261a43SJames C. McPherson 	    "for those devices\n"));
320a0261a43SJames C. McPherson 	(void) fprintf(stderr, gettext("\t\tattached via the specified "
321a0261a43SJames C. McPherson 	    "controller.\n"));
322a0261a43SJames C. McPherson 	(void) fprintf(stderr, gettext("\t-i\tinitialise the private devid "
323a0261a43SJames C. McPherson 	    "cache file and exit\n"));
324a0261a43SJames C. McPherson 	(void) fprintf(stderr, gettext("\t\tThis option excludes all "
325a0261a43SJames C. McPherson 	    "others.\n"));
326a0261a43SJames C. McPherson 	(void) fprintf(stderr, gettext("\t-n\tprint the devfs paths for "
327a0261a43SJames C. McPherson 	    "multipath-capable\n"));
328a0261a43SJames C. McPherson 	(void) fprintf(stderr, gettext("\t\tcontroller ports.\n"));
329a0261a43SJames C. McPherson 	(void) fprintf(stderr, gettext("\t-N\tprint the device aliases of "
330a0261a43SJames C. McPherson 	    "multipath-capable\n"));
331a0261a43SJames C. McPherson 	(void) fprintf(stderr, gettext("\t\tcontroller ports.\n"));
332a0261a43SJames C. McPherson 	(void) fprintf(stderr, gettext("\t-p\tdevname\n"));
333a0261a43SJames C. McPherson 	(void) fprintf(stderr, gettext("\t\tThis option provides the physical "
334a0261a43SJames C. McPherson 	    "devfs path for\n"));
335a0261a43SJames C. McPherson 	(void) fprintf(stderr, gettext("\t\ta specific device (devname). Used "
336a0261a43SJames C. McPherson 	    "to set the bootpath\n"));
337a0261a43SJames C. McPherson 	(void) fprintf(stderr, gettext("\t\tvariable on x86/x64 systems\n"));
338a0261a43SJames C. McPherson 	(void) fprintf(stderr, gettext("\t-u\ttranslates device mappings in "
339a0261a43SJames C. McPherson 	    "/etc/vfstab as \n"));
340a0261a43SJames C. McPherson 	(void) fprintf(stderr, gettext("\t\trequired. The output is written "
341a0261a43SJames C. McPherson 	    "to /etc/mpxio/vfstab.new\n\n"));
342a0261a43SJames C. McPherson 	exit(2);
343a0261a43SJames C. McPherson }
344a0261a43SJames C. McPherson 
3457c478bd9Sstevel@tonic-gate static void
3467c478bd9Sstevel@tonic-gate parse_args(int argc, char *argv[])
3477c478bd9Sstevel@tonic-gate {
3487c478bd9Sstevel@tonic-gate 	char opt;
3497c478bd9Sstevel@tonic-gate 
350a0261a43SJames C. McPherson 	if (argc == 1)
351a0261a43SJames C. McPherson 		usage();
3527c478bd9Sstevel@tonic-gate 
353a0261a43SJames C. McPherson 	/*
354a0261a43SJames C. McPherson 	 * -b	prints the bootpath property
355a0261a43SJames C. McPherson 	 * -d	turns on debug mode for this utility (copious output!)
356a0261a43SJames C. McPherson 	 * -D drvname
357a0261a43SJames C. McPherson 	 *	if supplied, indicates that we're going to operate on
358a0261a43SJames C. McPherson 	 *	devices attached to this driver.
359a0261a43SJames C. McPherson 	 * -g	if (-l or -L), prints guids for devices rather than paths
360a0261a43SJames C. McPherson 	 * -h	prints the usage() help text.
361a0261a43SJames C. McPherson 	 * -i	initialises the cache file and exits.
362a0261a43SJames C. McPherson 	 * -l controller
363a0261a43SJames C. McPherson 	 *	list non-STMS to STMS device name mappings for the specific
364a0261a43SJames C. McPherson 	 *	controller, when MPxIO is enabled only.
365a0261a43SJames C. McPherson 	 * -L	list non-STMS to STMS device name mappings for all controllers
366a0261a43SJames C. McPherson 	 *	when MPxIO is enabled only.
367a0261a43SJames C. McPherson 	 * -m devname
368a0261a43SJames C. McPherson 	 *	prints the device path (/dev/rdsk) that devname maps to
369a0261a43SJames C. McPherson 	 *	in the currently-running system.
370a0261a43SJames C. McPherson 	 * -n
371a0261a43SJames C. McPherson 	 *	if supplied, returns name of STMS-capable controller nodes.
372a0261a43SJames C. McPherson 	 *	If the -D drvname option is specified as well, we only report
373a0261a43SJames C. McPherson 	 *	nodes attached with drvname.
374a0261a43SJames C. McPherson 	 * -N
375a0261a43SJames C. McPherson 	 *	same as the -n option, except that we only print the
376a0261a43SJames C. McPherson 	 *	node-name (dev_info :: devi_node_name). Multiple instances
377a0261a43SJames C. McPherson 	 *	through the libdevinfo snapshot are uniqified and separated
378a0261a43SJames C. McPherson 	 *	by the "|" character for direct use by egrep(1).
379a0261a43SJames C. McPherson 	 * -p devname
380a0261a43SJames C. McPherson 	 *	prints the physical devfs path for devname. Only used to
381a0261a43SJames C. McPherson 	 *	determine the bootpath.
382a0261a43SJames C. McPherson 	 * -u
383a0261a43SJames C. McPherson 	 *	remaps devices in /etc/vfstab, saving the newly generated
384a0261a43SJames C. McPherson 	 *	file to /etc/mpxio/vfstab.new. If we have any remapped
385a0261a43SJames C. McPherson 	 *	devices, exit with status 0, otherwise -1 for error.
386a0261a43SJames C. McPherson 	 */
387a0261a43SJames C. McPherson 	while ((opt = getopt(argc, argv, "bdD:ghil:Lm:nNp:u")) != EOF) {
3887c478bd9Sstevel@tonic-gate 		switch (opt) {
389a0261a43SJames C. McPherson 		case 'b':
390a0261a43SJames C. McPherson 			globarg = MPX_BOOTPATH;
3917c478bd9Sstevel@tonic-gate 			break;
3927c478bd9Sstevel@tonic-gate 		case 'd':
393a0261a43SJames C. McPherson 			debugflag = 1;
3947c478bd9Sstevel@tonic-gate 			break;
39560fffc19Sjw149990 		case 'D':
396a0261a43SJames C. McPherson 			if ((drvlimit = calloc(1, MAXMODCONFNAME)) == NULL) {
397a0261a43SJames C. McPherson 				logmsg(MSG_ERROR,
398a0261a43SJames C. McPherson 				    gettext("Unable to allocate memory for a "
399a0261a43SJames C. McPherson 				    "driver name: %s\n"), strerror(errno));
400a0261a43SJames C. McPherson 				exit(errno);
40160fffc19Sjw149990 			}
402a0261a43SJames C. McPherson 			bcopy(optarg, drvlimit, strlen(optarg));
403a0261a43SJames C. McPherson 			/* update this if adding support for a new driver */
404a0261a43SJames C. McPherson 			if ((strncmp(drvlimit, "fp", 2) == NULL) &&
4055b504601Sjiang wu - Sun Microsystems - Beijing China 			    (strncmp(drvlimit, "mpt", 3) == NULL) &&
406*4c06356bSdh142964 			    (strncmp(drvlimit, "mpt_sas", 7) == NULL) &&
407*4c06356bSdh142964 			    (strncmp(drvlimit, "pmcs", 4) == NULL)) {
408a0261a43SJames C. McPherson 				logmsg(MSG_ERROR,
409a0261a43SJames C. McPherson 				    gettext("invalid parent driver (%s) "
410a0261a43SJames C. McPherson 				    "specified"), drvlimit);
411a0261a43SJames C. McPherson 				usage();
412a0261a43SJames C. McPherson 			}
41360fffc19Sjw149990 			break;
414a0261a43SJames C. McPherson 		case 'h':
415a0261a43SJames C. McPherson 			/* Just drop out and print the usage() output */
416a0261a43SJames C. McPherson 			globarg = MPX_USAGE;
417a0261a43SJames C. McPherson 			break;
418a0261a43SJames C. McPherson 		case 'i':
419a0261a43SJames C. McPherson 			globarg = MPX_INIT;
420a0261a43SJames C. McPherson 			break;
421a0261a43SJames C. McPherson 		case 'l':
422a0261a43SJames C. McPherson 			globarg |= MPX_LIST;
423a0261a43SJames C. McPherson 			limctrl = (int)atol(optarg);
424a0261a43SJames C. McPherson 			if (limctrl < 0) {
425a0261a43SJames C. McPherson 				logmsg(MSG_INFO,
426a0261a43SJames C. McPherson 				    gettext("invalid controller number "
427a0261a43SJames C. McPherson 				    "(%d), checking all controllers\n"),
428a0261a43SJames C. McPherson 				    limctrl);
429a0261a43SJames C. McPherson 			}
430a0261a43SJames C. McPherson 			break;
431a0261a43SJames C. McPherson 		case 'L':
432a0261a43SJames C. McPherson 			globarg |= MPX_LIST;
433a0261a43SJames C. McPherson 			break;
434a0261a43SJames C. McPherson 		case 'g':
435a0261a43SJames C. McPherson 			guid = 1;
436a0261a43SJames C. McPherson 			break;
437a0261a43SJames C. McPherson 		case 'm':
438a0261a43SJames C. McPherson 			globarg = MPX_MAP;
439a0261a43SJames C. McPherson 			if ((devicep = calloc(1, MAXPATHLEN)) == NULL) {
440a0261a43SJames C. McPherson 				logmsg(MSG_ERROR,
441a0261a43SJames C. McPherson 				    gettext("Unable to allocate space for a "
442a0261a43SJames C. McPherson 				    "device name\n"));
443a0261a43SJames C. McPherson 				exit(errno);
444a0261a43SJames C. McPherson 			}
445a0261a43SJames C. McPherson 			devicep = strdup(optarg);
446a0261a43SJames C. McPherson 			break;
447a0261a43SJames C. McPherson 		case 'N':
448a0261a43SJames C. McPherson 			cap_N_option = 1;
449a0261a43SJames C. McPherson 			globarg = MPX_CAPABLE_CTRL;
450a0261a43SJames C. McPherson 			break;
45160fffc19Sjw149990 		case 'n':
452a0261a43SJames C. McPherson 			globarg = MPX_CAPABLE_CTRL;
45360fffc19Sjw149990 			break;
454a0261a43SJames C. McPherson 		case 'p':
455a0261a43SJames C. McPherson 			globarg = MPX_PHYSICAL;
456a0261a43SJames C. McPherson 			if ((devicep = calloc(1, MAXPATHLEN)) == NULL) {
457a0261a43SJames C. McPherson 				logmsg(MSG_ERROR,
458a0261a43SJames C. McPherson 				    gettext("Unable to allocate space for a "
459a0261a43SJames C. McPherson 				    "device name\n"));
460a0261a43SJames C. McPherson 				exit(errno);
461a0261a43SJames C. McPherson 			}
462a0261a43SJames C. McPherson 			devicep = strdup(optarg);
463a0261a43SJames C. McPherson 			break;
464a0261a43SJames C. McPherson 		case 'u':
465a0261a43SJames C. McPherson 			globarg = MPX_UPDATEVFSTAB;
466a0261a43SJames C. McPherson 			break;
4677c478bd9Sstevel@tonic-gate 		default:
468a0261a43SJames C. McPherson 			logmsg(MSG_ERROR,
469a0261a43SJames C. McPherson 			    gettext("Invalid command line option (%c)\n"),
470a0261a43SJames C. McPherson 			    opt);
471a0261a43SJames C. McPherson 			usage();
4727c478bd9Sstevel@tonic-gate 		}
4737c478bd9Sstevel@tonic-gate 	}
4747c478bd9Sstevel@tonic-gate 
475a0261a43SJames C. McPherson 	if ((globarg >= MPX_USAGE) || (guid && (globarg != MPX_LIST)))
476a0261a43SJames C. McPherson 		usage();
477a0261a43SJames C. McPherson 
478a0261a43SJames C. McPherson 	if ((drvlimit != NULL) &&
479a0261a43SJames C. McPherson 	    ((globarg != MPX_LIST) &&
480a0261a43SJames C. McPherson 	    (globarg != MPX_CAPABLE_CTRL)))
481a0261a43SJames C. McPherson 		usage();
48260fffc19Sjw149990 }
4837c478bd9Sstevel@tonic-gate 
484a0261a43SJames C. McPherson static void
485a0261a43SJames C. McPherson logmsg(int level, const char *msg, ...)
4867c478bd9Sstevel@tonic-gate {
487a0261a43SJames C. McPherson 	va_list ap;
4887c478bd9Sstevel@tonic-gate 
489a0261a43SJames C. McPherson 	if ((level >= MSG_ERROR) ||
490a0261a43SJames C. McPherson 	    ((debugflag > 0) && (level >= MSG_INFO))) {
491a0261a43SJames C. McPherson 		(void) fprintf(stdout, "stmsboot: ");
492a0261a43SJames C. McPherson 		va_start(ap, msg);
493a0261a43SJames C. McPherson 		(void) vfprintf(stdout, msg, ap);
494a0261a43SJames C. McPherson 		va_end(ap);
4957c478bd9Sstevel@tonic-gate 	}
4967c478bd9Sstevel@tonic-gate }
4977c478bd9Sstevel@tonic-gate 
4987c478bd9Sstevel@tonic-gate /*
499a0261a43SJames C. McPherson  * It's up to the caller to do any sorting or pretty-printing of the device
500a0261a43SJames C. McPherson  * mappings we report. Since we're storing the device links as just the cXtYdZ
501a0261a43SJames C. McPherson  * part, we'll add /dev/rdsk/ back on when we print the listing so we maintain
502a0261a43SJames C. McPherson  * compatibility with previous versions of this tool. There's a little bit
503a0261a43SJames C. McPherson  * of footwork involved to make sure that we show all the paths to a device
504a0261a43SJames C. McPherson  * rather than just the first one we stashed away.
5057c478bd9Sstevel@tonic-gate  */
5067c478bd9Sstevel@tonic-gate static void
507a0261a43SJames C. McPherson list_devs(int listguids, int ctrl)
5087c478bd9Sstevel@tonic-gate {
509a0261a43SJames C. McPherson 	nvlist_t *thisdevnvl;
510a0261a43SJames C. McPherson 	nvpair_t *pair;
511a0261a43SJames C. McPherson 	char *diskpath, *livepath, *key, *querydev;
512a0261a43SJames C. McPherson 	char *matchctrl = NULL;
513a0261a43SJames C. McPherson 	char checkctrl[MAXPATHLEN];
514a0261a43SJames C. McPherson 	int rv;
5157c478bd9Sstevel@tonic-gate 
516a0261a43SJames C. McPherson 	if (!mpxenabled) {
51735c62094Sjianfei wang - Sun Microsystems - Beijing China 		if (mpxprop) {
51835c62094Sjianfei wang - Sun Microsystems - Beijing China 			logmsg(MSG_ERROR, gettext("MPXIO disabled\n"));
51935c62094Sjianfei wang - Sun Microsystems - Beijing China 		} else {
52035c62094Sjianfei wang - Sun Microsystems - Beijing China 			logmsg(MSG_ERROR, gettext("No STMS devices have "
52135c62094Sjianfei wang - Sun Microsystems - Beijing China 			    "been found\n"));
52235c62094Sjianfei wang - Sun Microsystems - Beijing China 		}
523a0261a43SJames C. McPherson 		return;
5247c478bd9Sstevel@tonic-gate 	}
5257c478bd9Sstevel@tonic-gate 
526a0261a43SJames C. McPherson 	if (listguids) {
527a0261a43SJames C. McPherson 		(void) printf(gettext("non-STMS device name\t\t\tGUID\n"
528a0261a43SJames C. McPherson 		    "------------------------------------------"
529a0261a43SJames C. McPherson 		    "------------------------\n"));
5307c478bd9Sstevel@tonic-gate 	} else {
531a0261a43SJames C. McPherson 		(void) printf(gettext("non-STMS device name\t\t\t"
532a0261a43SJames C. McPherson 		    "STMS device name\n"
533a0261a43SJames C. McPherson 		    "------------------------------------------"
534a0261a43SJames C. McPherson 		    "------------------------\n"));
535a0261a43SJames C. McPherson 	}
536a0261a43SJames C. McPherson 
537a0261a43SJames C. McPherson 	bzero(checkctrl, MAXPATHLEN);
538a0261a43SJames C. McPherson 	pair = NULL;
539a0261a43SJames C. McPherson 	while ((pair = nvlist_next_nvpair(mapnvl, pair))
540a0261a43SJames C. McPherson 	    != NULL) {
541a0261a43SJames C. McPherson 		boolean_t livescsivhcip = B_FALSE;
542a0261a43SJames C. McPherson 
543a0261a43SJames C. McPherson 		if ((((rv = nvpair_value_string(pair, &querydev)) < 0) ||
544a0261a43SJames C. McPherson 		    ((key = nvpair_name(pair)) == NULL)) ||
545a0261a43SJames C. McPherson 		    ((strstr(key, "/pci") != NULL) ||
546a0261a43SJames C. McPherson 		    (strstr(key, "/sbus") != NULL) ||
547a0261a43SJames C. McPherson 		    (strstr(key, "/scsi_vhci") != NULL) ||
548a0261a43SJames C. McPherson 		    (strncmp(key, "id1", 3) == 0))) {
549a0261a43SJames C. McPherson 			logmsg(MSG_INFO,
550a0261a43SJames C. McPherson 			    "list_devs: rv = %d; (%s) is not a devlink, "
551a0261a43SJames C. McPherson 			    "continuing.\n", rv,
552a0261a43SJames C. McPherson 			    (key != NULL) ? key : "null");
553a0261a43SJames C. McPherson 			querydev = NULL;
554a0261a43SJames C. McPherson 			continue;
555a0261a43SJames C. McPherson 		}
556a0261a43SJames C. McPherson 
557a0261a43SJames C. McPherson 		(void) nvlist_lookup_nvlist(mapnvl, querydev, &thisdevnvl);
558a0261a43SJames C. McPherson 		(void) nvlist_lookup_boolean_value(thisdevnvl, NVL_MPXEN,
559a0261a43SJames C. McPherson 		    &livescsivhcip);
560a0261a43SJames C. McPherson 		(void) nvlist_lookup_string(thisdevnvl, NVL_MPXPATH,
561a0261a43SJames C. McPherson 		    &livepath);
562a0261a43SJames C. McPherson 
563a0261a43SJames C. McPherson 		if ((!livescsivhcip) ||
564a0261a43SJames C. McPherson 		    (livescsivhcip &&
565a0261a43SJames C. McPherson 		    (strncmp(key, livepath, strlen(key)) == 0)))
566a0261a43SJames C. McPherson 			continue;
567a0261a43SJames C. McPherson 
568a0261a43SJames C. McPherson 		(void) nvlist_lookup_string(thisdevnvl, NVL_PATH,
569a0261a43SJames C. McPherson 		    &diskpath);
570a0261a43SJames C. McPherson 
571a0261a43SJames C. McPherson 		logmsg(MSG_INFO,
572a0261a43SJames C. McPherson 		    "list_devs: %s :: %s ::%s :: MPXEN (%s)\n",
573a0261a43SJames C. McPherson 		    key, diskpath, livepath,
574a0261a43SJames C. McPherson 		    ((livescsivhcip) ? "TRUE" : "FALSE"));
575a0261a43SJames C. McPherson 
576a0261a43SJames C. McPherson 		if (ctrl > -1) {
577a0261a43SJames C. McPherson 			(void) sprintf(checkctrl, "c%dt", ctrl);
578a0261a43SJames C. McPherson 			matchctrl = strstr(key, checkctrl);
579a0261a43SJames C. McPherson 			if (matchctrl == NULL)
580a0261a43SJames C. McPherson 				continue;
581a0261a43SJames C. McPherson 		}
582a0261a43SJames C. McPherson 		if (listguids != 0) {
583a0261a43SJames C. McPherson 			char *tempguid;
584a0261a43SJames C. McPherson 			ddi_devid_t curdevid;
585a0261a43SJames C. McPherson 			int rv;
586a0261a43SJames C. McPherson 
587a0261a43SJames C. McPherson 			rv = devid_str_decode(querydev, &curdevid, NULL);
588a0261a43SJames C. McPherson 			if (rv == -1) {
589a0261a43SJames C. McPherson 				logmsg(MSG_INFO, "Unable to decode devid %s\n",
590a0261a43SJames C. McPherson 				    key);
591a0261a43SJames C. McPherson 				continue;
592a0261a43SJames C. McPherson 			}
593a0261a43SJames C. McPherson 			tempguid = devid_to_guid(curdevid);
594a0261a43SJames C. McPherson 			if (tempguid != NULL)
595a0261a43SJames C. McPherson 				(void) printf("/dev/rdsk/%s\t%s\n",
596a0261a43SJames C. McPherson 				    diskpath, tempguid);
597a0261a43SJames C. McPherson 
598a0261a43SJames C. McPherson 			devid_free_guid(tempguid);
599a0261a43SJames C. McPherson 			devid_free(curdevid);
600a0261a43SJames C. McPherson 			continue;
601a0261a43SJames C. McPherson 		}
602a0261a43SJames C. McPherson 
603a0261a43SJames C. McPherson 		(void) printf("/dev/rdsk/%s\t/dev/rdsk/%s\n",
604a0261a43SJames C. McPherson 		    (strstr(key, diskpath) == NULL) ? key : diskpath,
605a0261a43SJames C. McPherson 		    livepath);
6067c478bd9Sstevel@tonic-gate 	}
6077c478bd9Sstevel@tonic-gate }
6087c478bd9Sstevel@tonic-gate 
6097c478bd9Sstevel@tonic-gate /*
610a0261a43SJames C. McPherson  * We get passed a device name which we search the mapnvl for. If we find
611a0261a43SJames C. McPherson  * it, we print the mapping as it is found. It is up to the caller of this
612a0261a43SJames C. McPherson  * utility to do any pretty-printing of the results. If a device listed on
613a0261a43SJames C. McPherson  * the command line does not exist in the mapnvl, then we print NOT_MAPPED.
614a0261a43SJames C. McPherson  * Otherwise we print the command-line device name as it maps to what is
615a0261a43SJames C. McPherson  * stashed in the mapnvl - even if that's a "no change" device mapping.
6167c478bd9Sstevel@tonic-gate  *
617a0261a43SJames C. McPherson  * Example output (-p maps to physpath=BOOT)
618a0261a43SJames C. McPherson  * # /lib/mpxio/stmsboot_util -p \
619a0261a43SJames C. McPherson  *	/pci@0,0/pci1022,7450@2/pci1000,3060@3/sd@1,0:a
620a0261a43SJames C. McPherson  * /scsi_vhci/disk@g500000e011e17720:a
6217c478bd9Sstevel@tonic-gate  *
622a0261a43SJames C. McPherson  * Or the reverse:
623a0261a43SJames C. McPherson  * # /lib/mpxio/stmsboot_util -p /scsi_vhci/disk@g500000e011e17720:a
624a0261a43SJames C. McPherson  * /pci@0,0/pci1022,7450@2/pci1000,3060@3/sd@1,0:a
625a0261a43SJames C. McPherson  *
626a0261a43SJames C. McPherson  * For the -m option, used when we're trying to find the root device mapping:
627a0261a43SJames C. McPherson  *
628a0261a43SJames C. McPherson  * # /lib/mpxio/stmsboot_util -m /dev/dsk/c2t0d0s2
629a0261a43SJames C. McPherson  * /dev/dsk/c3t500000E011637CF0d0s2
630a0261a43SJames C. McPherson  */
631a0261a43SJames C. McPherson static void
632a0261a43SJames C. McPherson report_map(char *argdev, int physpath)
633a0261a43SJames C. McPherson {
634a0261a43SJames C. McPherson 	nvlist_t *thisdev;
635a0261a43SJames C. McPherson 	int rv = 0;
636a0261a43SJames C. McPherson 	char *thisdevid;
637a0261a43SJames C. McPherson 	char *mpxpath = NULL;
638a0261a43SJames C. McPherson 	char *prefixt = NULL;
639a0261a43SJames C. McPherson 	char *prefixp = NULL;
640a0261a43SJames C. McPherson 	char *stripdev = NULL;
641a0261a43SJames C. McPherson 	char *slice = NULL;
642a0261a43SJames C. McPherson 	boolean_t mpxenp;
643a0261a43SJames C. McPherson 	uint_t slicelen = 0;
644a0261a43SJames C. McPherson 
645a0261a43SJames C. McPherson 	mpxenp = B_FALSE;
646a0261a43SJames C. McPherson 
647a0261a43SJames C. McPherson 	if ((prefixt = calloc(1, strlen(argdev) + 1)) == NULL) {
648a0261a43SJames C. McPherson 		logmsg(MSG_INFO, "Unable to allocate memory\n");
649a0261a43SJames C. McPherson 		(void) printf("NOT_MAPPED\n");
650a0261a43SJames C. McPherson 		return;
651a0261a43SJames C. McPherson 	}
652a0261a43SJames C. McPherson 
653a0261a43SJames C. McPherson 	(void) strlcpy(prefixt, argdev, strlen(argdev) + 1);
654a0261a43SJames C. McPherson 
655a0261a43SJames C. McPherson 	slice = strrchr(argdev, (physpath == BOOT) ? ':' : 's');
656a0261a43SJames C. McPherson 	if (slice != NULL) {
657a0261a43SJames C. McPherson 		slicelen = strlen(slice);
658a0261a43SJames C. McPherson 		if (slicelen > 3)
659a0261a43SJames C. McPherson 			/* invalid size - max is 3 chars */
660a0261a43SJames C. McPherson 			slicelen = 0;
661a0261a43SJames C. McPherson 	}
662a0261a43SJames C. McPherson 
663a0261a43SJames C. McPherson 	if ((stripdev = calloc(1, strlen(prefixt) + 1)) == NULL) {
664a0261a43SJames C. McPherson 		logmsg(MSG_INFO, "Unable to allocate memory\n");
665a0261a43SJames C. McPherson 		(void) printf("NOT_MAPPED\n");
666a0261a43SJames C. McPherson 		free(prefixt);
667a0261a43SJames C. McPherson 		return;
668a0261a43SJames C. McPherson 	}
669a0261a43SJames C. McPherson 
670a0261a43SJames C. McPherson 	if ((strstr(prefixt, "/scsi_vhci") == NULL) &&
671a0261a43SJames C. McPherson 	    (strstr(prefixt, "/pci") == NULL) &&
672a0261a43SJames C. McPherson 	    (strstr(prefixt, "/sbus") == NULL)) {
673a0261a43SJames C. McPherson 		prefixp = strrchr(prefixt, '/');
674a0261a43SJames C. McPherson 		(void) strlcpy(stripdev,
675a0261a43SJames C. McPherson 		    (prefixp == NULL) ? prefixt : prefixp + 1,
676a0261a43SJames C. McPherson 		    (prefixp == NULL) ?
677a0261a43SJames C. McPherson 		    strlen(prefixt) + 1: strlen(prefixp) + 1);
678a0261a43SJames C. McPherson 		if (prefixp != NULL)
679a0261a43SJames C. McPherson 			prefixt[strlen(argdev) - strlen(prefixp) + 1] = '\0';
680a0261a43SJames C. McPherson 	} else {
681a0261a43SJames C. McPherson 		if (physpath != BOOT) {
682a0261a43SJames C. McPherson 			logmsg(MSG_INFO, "Invalid device path provided\n");
683a0261a43SJames C. McPherson 			(void) printf("NOT_MAPPED\n");
684a0261a43SJames C. McPherson 			free(stripdev);
685a0261a43SJames C. McPherson 			free(prefixt);
686a0261a43SJames C. McPherson 			return;
687a0261a43SJames C. McPherson 		}
688a0261a43SJames C. McPherson 		(void) strlcpy(stripdev, argdev, strlen(argdev) + 1);
689a0261a43SJames C. McPherson 	}
690a0261a43SJames C. McPherson 
691a0261a43SJames C. McPherson 	logmsg(MSG_INFO,
692a0261a43SJames C. McPherson 	    "stripdev (%s), prefixt(%s), prefixp(%s), slice(%s)\n",
693a0261a43SJames C. McPherson 	    (stripdev == NULL) ? "null" : stripdev,
694a0261a43SJames C. McPherson 	    (prefixt == NULL) ? "null" : prefixt,
695a0261a43SJames C. McPherson 	    (prefixp == NULL) ? "null" : prefixp,
696a0261a43SJames C. McPherson 	    (slice == NULL) ? "null" : slice);
697a0261a43SJames C. McPherson 
698a0261a43SJames C. McPherson 	if (slicelen > 0)
699a0261a43SJames C. McPherson 		stripdev[strlen(stripdev) - slicelen] = '\0';
700a0261a43SJames C. McPherson 
701a0261a43SJames C. McPherson 	/* search for the shortened version */
702a0261a43SJames C. McPherson 	rv = nvlist_lookup_string(mapnvl, stripdev, &thisdevid);
703a0261a43SJames C. McPherson 	if (rv) {
704a0261a43SJames C. McPherson 		if (physpath != BOOT) {
705a0261a43SJames C. McPherson 			logmsg(MSG_INFO,
706a0261a43SJames C. McPherson 			    "searched mapnvl for '%s', got %s (%d)\n",
707a0261a43SJames C. McPherson 			    stripdev, strerror(rv), rv);
708a0261a43SJames C. McPherson 			(void) printf("NOT_MAPPED\n");
709a0261a43SJames C. McPherson 			free(stripdev);
710a0261a43SJames C. McPherson 			free(prefixt);
711a0261a43SJames C. McPherson 			return;
712a0261a43SJames C. McPherson 		}
713a0261a43SJames C. McPherson 	}
714a0261a43SJames C. McPherson 
715a0261a43SJames C. McPherson 	logmsg(MSG_INFO, "device %s has devid %s\n", stripdev, thisdevid);
716a0261a43SJames C. McPherson 
717a0261a43SJames C. McPherson 	if (nvlist_lookup_nvlist(mapnvl, thisdevid, &thisdev) != 0) {
718a0261a43SJames C. McPherson 		logmsg(MSG_INFO, "device (%s) in mapnvl but "
719a0261a43SJames C. McPherson 		    "not mapped!\n", thisdevid);
720a0261a43SJames C. McPherson 		(void) printf("NOT_MAPPED\n");
721a0261a43SJames C. McPherson 		free(stripdev);
722a0261a43SJames C. McPherson 		free(prefixt);
723a0261a43SJames C. McPherson 		return;
724a0261a43SJames C. McPherson 	}
725a0261a43SJames C. McPherson 
726a0261a43SJames C. McPherson 	/* quick exit */
727a0261a43SJames C. McPherson 	if (!mpxenabled && (strstr(argdev, "/pci") != NULL ||
728a0261a43SJames C. McPherson 	    strstr(argdev, "/sbus") != NULL)) {
729a0261a43SJames C. McPherson 		(void) printf("%s\n", argdev);
730a0261a43SJames C. McPherson 		free(stripdev);
731a0261a43SJames C. McPherson 		free(prefixt);
732a0261a43SJames C. McPherson 		return;
733a0261a43SJames C. McPherson 	}
734a0261a43SJames C. McPherson 
735a0261a43SJames C. McPherson 	(void) nvlist_lookup_boolean_value(thisdev, NVL_MPXEN, &mpxenp);
736a0261a43SJames C. McPherson 
737a0261a43SJames C. McPherson 	if (physpath == BOOT) {
738a0261a43SJames C. McPherson 		(void) nvlist_lookup_string(thisdev, NVL_PHYSPATH, &mpxpath);
739a0261a43SJames C. McPherson 		if ((strstr(argdev, "/scsi_vhci") != NULL) &&
740a0261a43SJames C. McPherson 		    (strncmp(argdev, mpxpath, strlen(mpxpath)) == 0)) {
741a0261a43SJames C. McPherson 			/* Need to translate vhci to phci */
742a0261a43SJames C. McPherson 			char *realpath;
743a0261a43SJames C. McPherson 
744a0261a43SJames C. McPherson 			if ((realpath = calloc(1, MAXPATHLEN + 1)) == NULL) {
745a0261a43SJames C. McPherson 				logmsg(MSG_ERROR,
746a0261a43SJames C. McPherson 				    gettext("Unable to allocate "
747a0261a43SJames C. McPherson 				    "memory for a path element\n"));
748a0261a43SJames C. McPherson 				free(stripdev);
749a0261a43SJames C. McPherson 				free(prefixt);
750a0261a43SJames C. McPherson 				return;
751a0261a43SJames C. McPherson 			}
752a0261a43SJames C. McPherson 			vhci_to_phci(stripdev, realpath);
753a0261a43SJames C. McPherson 			(void) printf("%s%s\n", realpath,
754a0261a43SJames C. McPherson 			    ((slicelen > 0) && slice != NULL) ? slice : "");
755a0261a43SJames C. McPherson 			free(realpath);
756a0261a43SJames C. McPherson 		} else {
757a0261a43SJames C. McPherson 			(void) printf("%s%s\n", mpxpath,
758a0261a43SJames C. McPherson 			    ((slicelen > 0) && slice != NULL) ? slice : "");
759a0261a43SJames C. McPherson 		}
760a0261a43SJames C. McPherson 	} else {
761a0261a43SJames C. McPherson 		(void) nvlist_lookup_string(thisdev,
762a0261a43SJames C. McPherson 		    ((readonlyroot) ? NVL_PHYSPATH :
763a0261a43SJames C. McPherson 		    ((mpxenp == B_TRUE) ? NVL_MPXPATH : NVL_PATH)),
764a0261a43SJames C. McPherson 		    &mpxpath);
765a0261a43SJames C. McPherson 		logmsg(MSG_INFO, "mpxpath = %s\n",
766a0261a43SJames C. McPherson 		    (mpxpath == NULL) ? "null" : mpxpath);
767a0261a43SJames C. McPherson 		if (readonlyroot ||
768a0261a43SJames C. McPherson 		    (strstr(mpxpath, "/scsi_vhci") != NULL) ||
769a0261a43SJames C. McPherson 		    (strstr(mpxpath, "/pci") != NULL) ||
770a0261a43SJames C. McPherson 		    (strstr(mpxpath, "/sbus") != NULL)) {
771a0261a43SJames C. McPherson 			/*
772a0261a43SJames C. McPherson 			 * If we see a physical path here it means that
773a0261a43SJames C. McPherson 			 * devlinks aren't fully initialised yet, so we
774a0261a43SJames C. McPherson 			 * are still in maintenance/single-user mode.
775a0261a43SJames C. McPherson 			 */
776a0261a43SJames C. McPherson 			(void) printf("/devices%s:%c\n", mpxpath,
777a0261a43SJames C. McPherson 			    slice[1] + '1');
778a0261a43SJames C. McPherson 		} else {
779a0261a43SJames C. McPherson 			(void) printf("%s%s%s\n",
780a0261a43SJames C. McPherson 			    (prefixt[0] == '/') ? prefixt : "",
781a0261a43SJames C. McPherson 			    mpxpath,
782a0261a43SJames C. McPherson 			    ((slicelen > 0) && slice != NULL) ? slice : "");
783a0261a43SJames C. McPherson 		}
784a0261a43SJames C. McPherson 	}
785a0261a43SJames C. McPherson 	free(prefixt);
786a0261a43SJames C. McPherson 	free(stripdev);
787a0261a43SJames C. McPherson }
788a0261a43SJames C. McPherson 
789a0261a43SJames C. McPherson /*
790a0261a43SJames C. McPherson  * Validate the in-kernel and on-disk forms of our devid cache,
791a0261a43SJames C. McPherson  * returns  -1 for unfixable error and 0 for success.
7927c478bd9Sstevel@tonic-gate  */
7937c478bd9Sstevel@tonic-gate static int
794a0261a43SJames C. McPherson validate_devnvl()
795a0261a43SJames C. McPherson {
796a0261a43SJames C. McPherson 	di_node_t	curnode;
797a0261a43SJames C. McPherson 	int		rv1 = -1;
798a0261a43SJames C. McPherson 	int		rv2 = -1;
799a0261a43SJames C. McPherson 
800a0261a43SJames C. McPherson 	/*
801a0261a43SJames C. McPherson 	 * Method: we walk through the kernel's concept of the device tree
802a0261a43SJames C. McPherson 	 * looking for "ssd" then "sd" nodes.
803a0261a43SJames C. McPherson 	 * We check to see whether the device's devid is already in our nvlist
804a0261a43SJames C. McPherson 	 * (on disk) nvlist cache file. If it is, we check that it's components
805a0261a43SJames C. McPherson 	 * match what we've got already and fill any missing fields.
806a0261a43SJames C. McPherson 	 * If the devid isn't in our on-disk nvlist already then we add it
807a0261a43SJames C. McPherson 	 * and populate the property nvpairs.
808a0261a43SJames C. McPherson 	 *
809a0261a43SJames C. McPherson 	 * At the end of this function we should have this program's concept
810a0261a43SJames C. McPherson 	 * of the devid-keyed nvlist matching what is in the ondisk form which
811a0261a43SJames C. McPherson 	 * is ready to be written out.
812a0261a43SJames C. McPherson 	 * If we can't do this, then we return -1.
813a0261a43SJames C. McPherson 	 */
814a0261a43SJames C. McPherson 	curnode = di_drv_first_node("ssd", devinfo_root);
815a0261a43SJames C. McPherson 	if (curnode != DI_NODE_NIL)
816a0261a43SJames C. McPherson 		rv1 = mpxio_nvl_boilerplate(curnode);
817a0261a43SJames C. McPherson 
818a0261a43SJames C. McPherson 	curnode = di_drv_first_node("sd", devinfo_root);
819a0261a43SJames C. McPherson 	if (curnode != DI_NODE_NIL)
820a0261a43SJames C. McPherson 		rv2 = mpxio_nvl_boilerplate(curnode);
821a0261a43SJames C. McPherson 
822a0261a43SJames C. McPherson 	if (rv1 + rv2 == -2)
823a0261a43SJames C. McPherson 		return (-1);
824a0261a43SJames C. McPherson 
825a0261a43SJames C. McPherson 	return (0);
826a0261a43SJames C. McPherson }
827a0261a43SJames C. McPherson 
828a0261a43SJames C. McPherson static int
829a0261a43SJames C. McPherson mpxio_nvl_boilerplate(di_node_t curnode)
830a0261a43SJames C. McPherson {
831a0261a43SJames C. McPherson 	int		rv;
832a0261a43SJames C. McPherson 	char		*strdevid;
833a0261a43SJames C. McPherson 	ddi_devid_t	curdevid;
834a0261a43SJames C. McPherson 	nvlist_t	*newnvl;
835a0261a43SJames C. McPherson 
836a0261a43SJames C. McPherson 	for (; curnode != DI_NODE_NIL; curnode = di_drv_next_node(curnode)) {
837a0261a43SJames C. McPherson 		errno = 0;
838a0261a43SJames C. McPherson 
839a0261a43SJames C. McPherson 		curdevid = NULL;
840a0261a43SJames C. McPherson 		get_devid(curnode, &curdevid);
841a0261a43SJames C. McPherson 		if (curdevid == NULL)
842a0261a43SJames C. McPherson 			/*
843a0261a43SJames C. McPherson 			 * There's no devid registered for this device
844a0261a43SJames C. McPherson 			 * so it's not cool enough to play with us
845a0261a43SJames C. McPherson 			 */
846a0261a43SJames C. McPherson 			continue;
847a0261a43SJames C. McPherson 
848a0261a43SJames C. McPherson 		strdevid = devid_str_encode(curdevid, NULL);
849a0261a43SJames C. McPherson 		/* does this exist in the on-disk cache? */
850a0261a43SJames C. McPherson 		rv = nvlist_lookup_nvlist(mapnvl, strdevid, &newnvl);
851a0261a43SJames C. McPherson 		if (rv == ENOENT) {
852a0261a43SJames C. McPherson 			logmsg(MSG_INFO, "nvlist for %s not found\n", strdevid);
853a0261a43SJames C. McPherson 			/* no, so alloc a new nvl to store it */
854a0261a43SJames C. McPherson 			if (nvlist_alloc(&newnvl, NV_UNIQUE_NAME, 0) != 0) {
855a0261a43SJames C. McPherson 				logmsg(MSG_ERROR,
856a0261a43SJames C. McPherson 				    gettext("Unable to allocate space for "
857a0261a43SJames C. McPherson 				    "a devid property list: %s\n"),
858a0261a43SJames C. McPherson 				    strerror(errno));
859a0261a43SJames C. McPherson 				return (-1);
860a0261a43SJames C. McPherson 			}
861a0261a43SJames C. McPherson 		} else {
862a0261a43SJames C. McPherson 			if ((rv != ENOTSUP) && (rv != EINVAL))
863a0261a43SJames C. McPherson 				logmsg(MSG_INFO,
864a0261a43SJames C. McPherson 				    "%s exists in ondisknvl, verifying\n",
865a0261a43SJames C. McPherson 				    strdevid);
866a0261a43SJames C. McPherson 		}
867a0261a43SJames C. McPherson 
868a0261a43SJames C. McPherson 		if (popcheck_devnvl(curnode, newnvl, strdevid) != 0) {
869a0261a43SJames C. McPherson 			logmsg(MSG_ERROR,
870a0261a43SJames C. McPherson 			    gettext("Unable to populate devid nvpair "
871a0261a43SJames C. McPherson 			    "for device with devid %s\n"),
872a0261a43SJames C. McPherson 			    strdevid);
873a0261a43SJames C. McPherson 			devid_str_free(strdevid);
874a0261a43SJames C. McPherson 			nvlist_free(newnvl);
875a0261a43SJames C. McPherson 			return (-1);
876a0261a43SJames C. McPherson 		}
877a0261a43SJames C. McPherson 
878a0261a43SJames C. McPherson 		/* Now add newnvl into our cache. */
879a0261a43SJames C. McPherson 		errno = 0;
880a0261a43SJames C. McPherson 		rv = nvlist_add_nvlist(mapnvl, strdevid, newnvl);
881a0261a43SJames C. McPherson 		if (rv) {
882a0261a43SJames C. McPherson 			logmsg(MSG_ERROR,
883a0261a43SJames C. McPherson 			    gettext("Unable to add device (devid %s) "
884a0261a43SJames C. McPherson 			    "to in-kernel nvl: %s (%d)\n"),
885a0261a43SJames C. McPherson 			    strdevid, strerror(rv), rv);
886a0261a43SJames C. McPherson 			devid_str_free(strdevid);
887a0261a43SJames C. McPherson 			nvlist_free(newnvl);
888a0261a43SJames C. McPherson 			return (-1);
889a0261a43SJames C. McPherson 		}
890a0261a43SJames C. McPherson 		logmsg(MSG_INFO,
891a0261a43SJames C. McPherson 		    gettext("added device (devid %s) to mapnvl\n\n"),
892a0261a43SJames C. McPherson 		    strdevid);
893a0261a43SJames C. McPherson 		devid_str_free(strdevid);
894a0261a43SJames C. McPherson 	}
895a0261a43SJames C. McPherson 	return (0);
896a0261a43SJames C. McPherson }
897a0261a43SJames C. McPherson 
898a0261a43SJames C. McPherson /*
899a0261a43SJames C. McPherson  * Operates on a single di_node_t, collecting all the device properties
900a0261a43SJames C. McPherson  * that we need. devnvl is allocated by the caller, and we add our nvpairs
901a0261a43SJames C. McPherson  * to it if they don't already exist.
902a0261a43SJames C. McPherson  *
903a0261a43SJames C. McPherson  * We are _only_ interested in devices which have a devid. We pull in
904a0261a43SJames C. McPherson  * devices even when they're excluded via stmsboot -D (driver), because
905a0261a43SJames C. McPherson  * we don't want to miss out on any devid data that might be handy later.
906a0261a43SJames C. McPherson  */
907a0261a43SJames C. McPherson static int
908a0261a43SJames C. McPherson popcheck_devnvl(di_node_t thisnode, nvlist_t *devnvl, char *strdevid)
909a0261a43SJames C. McPherson {
910a0261a43SJames C. McPherson 	char *path = NULL;
911a0261a43SJames C. McPherson 	char *curpath = NULL;
912a0261a43SJames C. McPherson 	char *devfspath = NULL;
91335c62094Sjianfei wang - Sun Microsystems - Beijing China 	char *prop = NULL;
914a0261a43SJames C. McPherson 	int scsivhciparent = 0;
915a0261a43SJames C. McPherson 	int rv = 0;
916a0261a43SJames C. McPherson 	boolean_t mpxenp = B_FALSE;
917a0261a43SJames C. McPherson 
918a0261a43SJames C. McPherson 	errno = 0;
919a0261a43SJames C. McPherson 	devfspath = di_devfs_path(thisnode);
920a0261a43SJames C. McPherson 	if (devfspath == NULL) {
921a0261a43SJames C. McPherson 		logmsg(MSG_ERROR,
922a0261a43SJames C. McPherson 		    gettext("Unable to determine devfs path for node: %s\n"),
923a0261a43SJames C. McPherson 		    strerror(errno));
924a0261a43SJames C. McPherson 		return (-1);
925a0261a43SJames C. McPherson 	}
926a0261a43SJames C. McPherson 
927a0261a43SJames C. McPherson 	/* Add a convenient devfspath to devid inverse map */
928a0261a43SJames C. McPherson 	if (nvlist_add_string(mapnvl, devfspath, strdevid) != 0) {
929a0261a43SJames C. McPherson 		logmsg(MSG_ERROR,
930a0261a43SJames C. McPherson 		    gettext("Unable to add device path %s with devid "
931a0261a43SJames C. McPherson 		    "%s to mapnvl\n"), devfspath, strdevid);
932a0261a43SJames C. McPherson 		return (-1);
933a0261a43SJames C. McPherson 	}
93435c62094Sjianfei wang - Sun Microsystems - Beijing China 	if (di_prop_lookup_strings(DDI_DEV_T_ANY, di_parent_node(thisnode),
93535c62094Sjianfei wang - Sun Microsystems - Beijing China 	    "mpxio-disable", &prop) >= 0) {
93635c62094Sjianfei wang - Sun Microsystems - Beijing China 		if (strncmp(prop, "yes", 3) == 0) {
93735c62094Sjianfei wang - Sun Microsystems - Beijing China 			if (!mpxprop)
93835c62094Sjianfei wang - Sun Microsystems - Beijing China 				mpxprop++;
93935c62094Sjianfei wang - Sun Microsystems - Beijing China 		}
94035c62094Sjianfei wang - Sun Microsystems - Beijing China 	}
94135c62094Sjianfei wang - Sun Microsystems - Beijing China 
942a0261a43SJames C. McPherson 	if (strncmp(di_driver_name(di_parent_node(thisnode)),
943a0261a43SJames C. McPherson 	    "scsi_vhci", 9) == 0) {
944a0261a43SJames C. McPherson 		scsivhciparent = 1;
945a0261a43SJames C. McPherson 		if (!mpxenabled)
946a0261a43SJames C. McPherson 			mpxenabled++;
947a0261a43SJames C. McPherson 
948a0261a43SJames C. McPherson 		rv = nvlist_lookup_boolean_value(devnvl, NVL_MPXEN, &mpxenp);
949a0261a43SJames C. McPherson 		if (rv || (mpxenp == B_FALSE)) {
950a0261a43SJames C. McPherson 			rv = nvlist_add_boolean_value(devnvl,
951a0261a43SJames C. McPherson 			    NVL_MPXEN, B_TRUE);
952a0261a43SJames C. McPherson 			if (rv) {
953a0261a43SJames C. McPherson 				logmsg(MSG_ERROR,
954a0261a43SJames C. McPherson 				    gettext("Unable to add property %s "
955a0261a43SJames C. McPherson 				    "(set to B_TRUE) for device %s: "
956a0261a43SJames C. McPherson 				    "%s (%d)\n"),
957a0261a43SJames C. McPherson 				    NVL_MPXEN, devfspath,
958a0261a43SJames C. McPherson 				    strerror(rv), rv);
959a0261a43SJames C. McPherson 				return (-1);
960a0261a43SJames C. McPherson 			}
961a0261a43SJames C. McPherson 			logmsg(MSG_INFO, "NVL_MPXEN :: (B_FALSE->B_TRUE)\n");
962a0261a43SJames C. McPherson 		}
963a0261a43SJames C. McPherson 	} else {
964a0261a43SJames C. McPherson 		/* turn _off_ the flag if it was enabled */
965a0261a43SJames C. McPherson 		rv = nvlist_add_boolean_value(devnvl, NVL_MPXEN, B_FALSE);
966a0261a43SJames C. McPherson 		if (rv) {
967a0261a43SJames C. McPherson 			logmsg(MSG_ERROR,
968a0261a43SJames C. McPherson 			    gettext("Unable to add property %s "
969a0261a43SJames C. McPherson 			    "(set to B_FALSE) for device %s: %s (%d)\n"),
970a0261a43SJames C. McPherson 			    NVL_MPXEN, devfspath,
971a0261a43SJames C. McPherson 			    strerror(rv), rv);
972a0261a43SJames C. McPherson 			return (-1);
973a0261a43SJames C. McPherson 		}
974a0261a43SJames C. McPherson 		logmsg(MSG_INFO, "NVL_MPXEN :: (B_TRUE-> B_FALSE)\n");
975a0261a43SJames C. McPherson 	}
976a0261a43SJames C. McPherson 
977a0261a43SJames C. McPherson 	rv = nvlist_add_string(devnvl, NVL_PHYSPATH, devfspath);
978a0261a43SJames C. McPherson 	if (rv) {
979a0261a43SJames C. McPherson 		logmsg(MSG_ERROR,
980a0261a43SJames C. McPherson 		    gettext("Unable to add physical device path (%s) "
981a0261a43SJames C. McPherson 		    "property to nvl\n"));
982a0261a43SJames C. McPherson 		return (-1);
983a0261a43SJames C. McPherson 	}
984a0261a43SJames C. McPherson 
985a0261a43SJames C. McPherson 	if ((curpath = calloc(1, MAXPATHLEN)) == NULL) {
986a0261a43SJames C. McPherson 		logmsg(MSG_ERROR,
987a0261a43SJames C. McPherson 		    gettext("Unable to allocate space for current path\n"));
988a0261a43SJames C. McPherson 		return (-1);
989a0261a43SJames C. McPherson 	}
990a0261a43SJames C. McPherson 	curpath = find_link(thisnode);
991a0261a43SJames C. McPherson 	if (curpath == NULL) {
992a0261a43SJames C. McPherson 		if (readonlyroot) {
993a0261a43SJames C. McPherson 			return (0);
994a0261a43SJames C. McPherson 		}
995a0261a43SJames C. McPherson 		logmsg(MSG_ERROR,
996a0261a43SJames C. McPherson 		    gettext("Unable to determine device path for node %s\n"),
997a0261a43SJames C. McPherson 		    devfspath);
998a0261a43SJames C. McPherson 		return (-1);
999a0261a43SJames C. McPherson 	}
1000a0261a43SJames C. McPherson 
1001a0261a43SJames C. McPherson 	rv = nvlist_lookup_string(devnvl, NVL_MPXPATH, &path);
1002a0261a43SJames C. McPherson 
1003a0261a43SJames C. McPherson 	if (path == NULL && scsivhciparent)
1004a0261a43SJames C. McPherson 		(void) nvlist_add_string(devnvl, NVL_MPXPATH, curpath);
1005a0261a43SJames C. McPherson 
1006a0261a43SJames C. McPherson 	if (!scsivhciparent) {
1007a0261a43SJames C. McPherson 		(void) nvlist_add_string(devnvl, NVL_PATH, curpath);
1008a0261a43SJames C. McPherson 		path = curpath;
1009a0261a43SJames C. McPherson 	}
1010a0261a43SJames C. McPherson 
1011a0261a43SJames C. McPherson 	/*
1012a0261a43SJames C. McPherson 	 * This next block provides the path to devid inverse mapping
1013a0261a43SJames C. McPherson 	 * that other functions require
1014a0261a43SJames C. McPherson 	 */
1015a0261a43SJames C. McPherson 	if (path != NULL) {
1016a0261a43SJames C. McPherson 		if (nvlist_add_string(mapnvl, path, strdevid) != 0) {
1017a0261a43SJames C. McPherson 			logmsg(MSG_ERROR,
1018a0261a43SJames C. McPherson 			    gettext("Unable to add device %s with devid "
1019a0261a43SJames C. McPherson 			    "%s to mapnvl\n"), path, strdevid);
1020a0261a43SJames C. McPherson 			return (-1);
1021a0261a43SJames C. McPherson 		}
1022a0261a43SJames C. McPherson 		logmsg(MSG_INFO, "popcheck_devnvl: added path %s :: %s\n",
1023a0261a43SJames C. McPherson 		    path, strdevid);
1024a0261a43SJames C. McPherson 		if (nvlist_add_string(mapnvl, curpath, strdevid) != 0) {
1025a0261a43SJames C. McPherson 			logmsg(MSG_ERROR,
1026a0261a43SJames C. McPherson 			    gettext("Unable to add device %s with devid "
1027a0261a43SJames C. McPherson 			    "%s to mapnvl: %s\n"),
1028a0261a43SJames C. McPherson 			    curpath, strdevid, strerror(errno));
1029a0261a43SJames C. McPherson 			return (-1);
1030a0261a43SJames C. McPherson 		}
1031a0261a43SJames C. McPherson 		logmsg(MSG_INFO, "popcheck_devnvl: added curpath %s :: %s\n",
1032a0261a43SJames C. McPherson 		    curpath, strdevid);
1033a0261a43SJames C. McPherson 	}
1034a0261a43SJames C. McPherson 	if (scsivhciparent) {
1035a0261a43SJames C. McPherson 		if (nvlist_add_string(devnvl, NVL_MPXPATH, curpath) != 0) {
1036a0261a43SJames C. McPherson 			logmsg(MSG_ERROR,
1037a0261a43SJames C. McPherson 			    gettext("Unable to add property %s for device "
1038a0261a43SJames C. McPherson 			    "%s: %s\n"),
1039a0261a43SJames C. McPherson 			    NVL_MPXPATH, devfspath, strerror(errno));
1040a0261a43SJames C. McPherson 			return (-1);
1041a0261a43SJames C. McPherson 		} else {
1042a0261a43SJames C. McPherson 			logmsg(MSG_INFO, "added curpath (%s) as NVL_MPXPATH "
1043a0261a43SJames C. McPherson 			    "to devnvl for devid %s\n", curpath, strdevid);
1044a0261a43SJames C. McPherson 		}
1045a0261a43SJames C. McPherson 	}
1046a0261a43SJames C. McPherson 	return (0);
1047a0261a43SJames C. McPherson }
1048a0261a43SJames C. McPherson 
1049a0261a43SJames C. McPherson static void
1050a0261a43SJames C. McPherson print_mpx_capable(di_node_t curnode)
1051a0261a43SJames C. McPherson {
1052a0261a43SJames C. McPherson 	char *prop;
1053a0261a43SJames C. McPherson 	char *path;
1054a0261a43SJames C. McPherson 	char *aliases = NULL;
1055a0261a43SJames C. McPherson 
1056a0261a43SJames C. McPherson 	if (cap_N_option) {
1057a0261a43SJames C. McPherson 		aliases = calloc(1, MAXPATHLEN + 1);
1058a0261a43SJames C. McPherson 		if (aliases == NULL) {
1059a0261a43SJames C. McPherson 			logmsg(MSG_ERROR,
1060a0261a43SJames C. McPherson 			    gettext("Unable to allocate memory for a device "
1061a0261a43SJames C. McPherson 			    "alias list\n"));
1062a0261a43SJames C. McPherson 			return;
1063a0261a43SJames C. McPherson 		}
1064a0261a43SJames C. McPherson 	}
1065a0261a43SJames C. McPherson 
1066a0261a43SJames C. McPherson 	for (; curnode != DI_NODE_NIL; curnode = di_drv_next_node(curnode)) {
1067a0261a43SJames C. McPherson 		if (di_prop_lookup_strings(DDI_DEV_T_ANY, curnode,
1068a0261a43SJames C. McPherson 		    "initiator-port", &prop) >= 0) {
1069a0261a43SJames C. McPherson 			if ((path = di_devfs_path(curnode)) == NULL) {
1070a0261a43SJames C. McPherson 				logmsg(MSG_INFO,
1071a0261a43SJames C. McPherson 				    "Unable to find devfs path for device "
1072a0261a43SJames C. McPherson 				    "%s: %s\n", &curnode, strerror(errno));
1073a0261a43SJames C. McPherson 				continue;
1074a0261a43SJames C. McPherson 			}
1075a0261a43SJames C. McPherson 			if (cap_N_option) {
1076a0261a43SJames C. McPherson 				char *nodename = di_node_name(curnode);
1077a0261a43SJames C. McPherson 				/* nodename is never going to be null */
1078a0261a43SJames C. McPherson 				if (strstr(aliases, nodename) == NULL)
1079a0261a43SJames C. McPherson 					/* haven't seen this nodename before */
1080a0261a43SJames C. McPherson 					(void) snprintf(aliases,
1081a0261a43SJames C. McPherson 					    MAXPATHLEN + 1, "%s|%s",
1082a0261a43SJames C. McPherson 					    ((aliases != NULL) ? aliases : ""),
1083a0261a43SJames C. McPherson 					    nodename);
1084a0261a43SJames C. McPherson 			} else
1085a0261a43SJames C. McPherson 				(void) printf("%s\n", path);
1086a0261a43SJames C. McPherson 		}
1087a0261a43SJames C. McPherson 	}
1088a0261a43SJames C. McPherson 	if (cap_N_option)
1089a0261a43SJames C. McPherson 		(void) printf("%s\n", aliases);
1090a0261a43SJames C. McPherson }
1091a0261a43SJames C. McPherson 
1092a0261a43SJames C. McPherson static int
1093a0261a43SJames C. McPherson link_cb(di_devlink_t devlink, void *arg)
1094a0261a43SJames C. McPherson {
1095a0261a43SJames C. McPherson 	const char *result;
1096a0261a43SJames C. McPherson 
1097a0261a43SJames C. McPherson 	result = di_devlink_path(devlink);
1098a0261a43SJames C. McPherson 	if (result == NULL) {
1099a0261a43SJames C. McPherson 		arg = (void *)"(null)";
1100a0261a43SJames C. McPherson 	} else {
1101a0261a43SJames C. McPherson 		(void) strlcpy(arg, result, strlen(result));
1102a0261a43SJames C. McPherson 	}
1103a0261a43SJames C. McPherson 	logmsg(MSG_INFO, "\nlink_cb::linkdata->resultstr = %s\n",
1104a0261a43SJames C. McPherson 	    ((result != NULL) ? result : "(null)"));
1105a0261a43SJames C. McPherson 	return (DI_WALK_CONTINUE);
1106a0261a43SJames C. McPherson }
1107a0261a43SJames C. McPherson 
1108a0261a43SJames C. McPherson static char *
1109a0261a43SJames C. McPherson find_link(di_node_t cnode)
1110a0261a43SJames C. McPherson {
1111a0261a43SJames C. McPherson 	di_minor_t devminor = DI_MINOR_NIL;
1112a0261a43SJames C. McPherson 	di_devlink_handle_t	hdl;
1113a0261a43SJames C. McPherson 	char *devfspath = NULL;
1114a0261a43SJames C. McPherson 	char *minorpath = NULL;
1115a0261a43SJames C. McPherson 	char *linkname = NULL;
1116a0261a43SJames C. McPherson 	char *cbresult = NULL;
1117a0261a43SJames C. McPherson 
1118a0261a43SJames C. McPherson 	devfspath = di_devfs_path(cnode);
1119a0261a43SJames C. McPherson 	if (cnode == DI_NODE_NIL) {
1120a0261a43SJames C. McPherson 		logmsg(MSG_ERROR,
1121a0261a43SJames C. McPherson 		    gettext("find_ctrl must be called with non-null "
1122a0261a43SJames C. McPherson 		    "di_node_t\n"));
1123a0261a43SJames C. McPherson 		return (NULL);
1124a0261a43SJames C. McPherson 	}
1125a0261a43SJames C. McPherson 	logmsg(MSG_INFO, "find_link: devfspath %s\n", devfspath);
1126a0261a43SJames C. McPherson 
1127a0261a43SJames C. McPherson 	if (((cbresult = calloc(1, MAXPATHLEN)) == NULL) ||
1128a0261a43SJames C. McPherson 	    ((minorpath = calloc(1, MAXPATHLEN)) == NULL) ||
1129a0261a43SJames C. McPherson 	    ((linkname = calloc(1, MAXPATHLEN)) == NULL)) {
1130a0261a43SJames C. McPherson 		logmsg(MSG_ERROR, "unable to allocate space for dev link\n");
1131a0261a43SJames C. McPherson 		return (NULL);
1132a0261a43SJames C. McPherson 	}
1133a0261a43SJames C. McPherson 
1134a0261a43SJames C. McPherson 	devminor = di_minor_next(cnode, devminor);
1135a0261a43SJames C. McPherson 	hdl = di_devlink_init(di_devfs_minor_path(devminor), DI_MAKE_LINK);
1136a0261a43SJames C. McPherson 	if (hdl == NULL) {
1137a0261a43SJames C. McPherson 		logmsg((readonlyroot ? MSG_INFO : MSG_ERROR),
1138a0261a43SJames C. McPherson 		    gettext("unable to take devlink snapshot: %s\n"),
1139a0261a43SJames C. McPherson 		    strerror(errno));
1140a0261a43SJames C. McPherson 		return (NULL);
1141a0261a43SJames C. McPherson 	}
1142a0261a43SJames C. McPherson 
1143a0261a43SJames C. McPherson 	linkname = "^dsk/";
1144a0261a43SJames C. McPherson 	(void) snprintf(minorpath, MAXPATHLEN, "%s:c", devfspath);
1145a0261a43SJames C. McPherson 
1146a0261a43SJames C. McPherson 	errno = 0;
1147a0261a43SJames C. McPherson 	if (di_devlink_walk(hdl, linkname, minorpath, DI_PRIMARY_LINK,
1148a0261a43SJames C. McPherson 	    (void *)cbresult, link_cb) < 0) {
1149a0261a43SJames C. McPherson 		logmsg(MSG_ERROR,
1150a0261a43SJames C. McPherson 		    gettext("Unable to walk devlink snapshot for %s: %s\n"),
1151a0261a43SJames C. McPherson 		    minorpath, strerror(errno));
1152a0261a43SJames C. McPherson 		return (NULL);
1153a0261a43SJames C. McPherson 	}
1154a0261a43SJames C. McPherson 
1155a0261a43SJames C. McPherson 	if (di_devlink_fini(&hdl) < 0) {
1156a0261a43SJames C. McPherson 		logmsg(MSG_ERROR,
1157a0261a43SJames C. McPherson 		    gettext("Unable to close devlink snapshot: %s\n"),
1158a0261a43SJames C. McPherson 		    strerror(errno));
1159a0261a43SJames C. McPherson 	}
1160a0261a43SJames C. McPherson 	if (strstr(cbresult, "dsk/") == NULL)
1161a0261a43SJames C. McPherson 		return (devfspath);
1162a0261a43SJames C. McPherson 
1163a0261a43SJames C. McPherson 	bzero(minorpath, MAXPATHLEN);
1164a0261a43SJames C. McPherson 	/* strip off the trailing "s2" */
1165a0261a43SJames C. McPherson 	bcopy(cbresult, minorpath, strlen(cbresult) - 1);
1166a0261a43SJames C. McPherson 	/* Now strip off the /dev/dsk/ prefix for output flexibility */
1167a0261a43SJames C. McPherson 	linkname = strrchr(minorpath, '/');
1168a0261a43SJames C. McPherson 	return (++linkname);
1169a0261a43SJames C. McPherson }
1170a0261a43SJames C. McPherson 
1171a0261a43SJames C. McPherson /*
1172a0261a43SJames C. McPherson  * handle case where device has been probed but its target driver is not
1173a0261a43SJames C. McPherson  * attached so enumeration has not quite finished. Opening the /devices
1174a0261a43SJames C. McPherson  * pathname will force the kernel to finish the enumeration process and
1175a0261a43SJames C. McPherson  * let us get the data we need.
1176a0261a43SJames C. McPherson  */
1177a0261a43SJames C. McPherson static void
1178a0261a43SJames C. McPherson get_devid(di_node_t node, ddi_devid_t *thisdevid)
11797c478bd9Sstevel@tonic-gate {
11807c478bd9Sstevel@tonic-gate 	int fd;
1181a0261a43SJames C. McPherson 	char realpath[MAXPATHLEN];
1182a0261a43SJames C. McPherson 	char *openpath = di_devfs_path(node);
11837c478bd9Sstevel@tonic-gate 
1184a0261a43SJames C. McPherson 	errno = 0;
1185a0261a43SJames C. McPherson 	bzero(realpath, MAXPATHLEN);
1186a0261a43SJames C. McPherson 	if (strstr(openpath, "/devices") == NULL) {
1187a0261a43SJames C. McPherson 		(void) snprintf(realpath, MAXPATHLEN,
1188a0261a43SJames C. McPherson 		    "/devices%s:c,raw", openpath);
1189a0261a43SJames C. McPherson 		fd = open(realpath, O_RDONLY|O_NDELAY);
119060fffc19Sjw149990 	} else {
1191a0261a43SJames C. McPherson 		fd = open(openpath, O_RDONLY|O_NDELAY);
119260fffc19Sjw149990 	}
119360fffc19Sjw149990 
1194a0261a43SJames C. McPherson 	if (fd < 0) {
1195a0261a43SJames C. McPherson 		logmsg(MSG_INFO, "Unable to open path %s: %s\n",
1196a0261a43SJames C. McPherson 		    openpath, strerror(errno));
1197a0261a43SJames C. McPherson 		return;
11987c478bd9Sstevel@tonic-gate 	}
11997c478bd9Sstevel@tonic-gate 
1200a0261a43SJames C. McPherson 	if (devid_get(fd, thisdevid) != 0) {
1201a0261a43SJames C. McPherson 		logmsg(MSG_INFO,
1202a0261a43SJames C. McPherson 		    "'%s' node (%s) without a devid registered\n",
1203a0261a43SJames C. McPherson 		    di_driver_name(node), di_devfs_path(node));
120460fffc19Sjw149990 	}
12057c478bd9Sstevel@tonic-gate 	(void) close(fd);
12067c478bd9Sstevel@tonic-gate }
12077c478bd9Sstevel@tonic-gate 
12088cecff49Sgp87344 static int
1209a0261a43SJames C. McPherson print_bootpath()
12108cecff49Sgp87344 {
1211a0261a43SJames C. McPherson 	char *bootprop = NULL;
12128cecff49Sgp87344 
1213a0261a43SJames C. McPherson 	if (di_prop_lookup_strings(DDI_DEV_T_ANY, devinfo_root,
1214a0261a43SJames C. McPherson 	    "bootpath", &bootprop) >= 0) {
1215a0261a43SJames C. McPherson 		(void) printf("%s\n", bootprop);
12168cecff49Sgp87344 		return (0);
1217a0261a43SJames C. McPherson 	} else if (di_prop_lookup_strings(DDI_DEV_T_ANY, devinfo_root,
1218a0261a43SJames C. McPherson 	    "boot-path", &bootprop) >= 0) {
1219a0261a43SJames C. McPherson 		(void) printf("%s\n", bootprop);
1220a0261a43SJames C. McPherson 		return (0);
1221a0261a43SJames C. McPherson 	} else {
1222a0261a43SJames C. McPherson 		(void) printf("ERROR: no bootpath/boot-path property found\n");
1223a0261a43SJames C. McPherson 		return (ENOENT);
1224a0261a43SJames C. McPherson 	}
12258cecff49Sgp87344 }
12268cecff49Sgp87344 
12275b504601Sjiang wu - Sun Microsystems - Beijing China static void
12285b504601Sjiang wu - Sun Microsystems - Beijing China get_phci_driver_name(char *phci_path, char **driver_name)
12295b504601Sjiang wu - Sun Microsystems - Beijing China {
12305b504601Sjiang wu - Sun Microsystems - Beijing China 	di_node_t phci_node = DI_NODE_NIL;
12315b504601Sjiang wu - Sun Microsystems - Beijing China 	char *tmp = NULL;
12325b504601Sjiang wu - Sun Microsystems - Beijing China 
12335b504601Sjiang wu - Sun Microsystems - Beijing China 	phci_node = di_init(phci_path, DINFOCPYONE);
12345b504601Sjiang wu - Sun Microsystems - Beijing China 	if (phci_node == DI_NODE_NIL) {
12355b504601Sjiang wu - Sun Microsystems - Beijing China 		logmsg(MSG_ERROR,
12365b504601Sjiang wu - Sun Microsystems - Beijing China 		    gettext("Unable to take phci snapshot "
12375b504601Sjiang wu - Sun Microsystems - Beijing China 		    "(%s: %d)\n"), strerror(errno), errno);
12385b504601Sjiang wu - Sun Microsystems - Beijing China 		return;
12395b504601Sjiang wu - Sun Microsystems - Beijing China 	}
12405b504601Sjiang wu - Sun Microsystems - Beijing China 	tmp = di_driver_name(phci_node);
12415b504601Sjiang wu - Sun Microsystems - Beijing China 	if (tmp != NULL) {
12425b504601Sjiang wu - Sun Microsystems - Beijing China 		(void) strncpy(*driver_name, tmp, 10);
12435b504601Sjiang wu - Sun Microsystems - Beijing China 	}
12445b504601Sjiang wu - Sun Microsystems - Beijing China 	di_fini(phci_node);
12455b504601Sjiang wu - Sun Microsystems - Beijing China }
12468cecff49Sgp87344 /*
1247a0261a43SJames C. McPherson  * We only call this routine if we have a scsi_vhci node and must
1248a0261a43SJames C. McPherson  * determine the actual physical path of its first online client
1249a0261a43SJames C. McPherson  * path.
12507c478bd9Sstevel@tonic-gate  */
1251a0261a43SJames C. McPherson static void
1252a0261a43SJames C. McPherson vhci_to_phci(char *devpath, char *physpath)
12537c478bd9Sstevel@tonic-gate {
12547c478bd9Sstevel@tonic-gate 	sv_iocdata_t	ioc;
12555a4c37c9Sqh201292 	sv_path_info_t	*pi;
1256a0261a43SJames C. McPherson 	int		vhci_fd;
1257a0261a43SJames C. McPherson 	int		rv;
1258a0261a43SJames C. McPherson 	uint_t		npaths = 0;
12595a4c37c9Sqh201292 
1260a0261a43SJames C. McPherson 	vhci_fd = open(VHCI_CTL_NODE, O_RDWR);
1261a0261a43SJames C. McPherson 	if (vhci_fd < 0)
1262a0261a43SJames C. McPherson 		goto failure;
12635a4c37c9Sqh201292 
12645a4c37c9Sqh201292 	bzero(&ioc, sizeof (sv_iocdata_t));
1265a0261a43SJames C. McPherson 	ioc.client = devpath;
12665a4c37c9Sqh201292 	ioc.ret_elem = &npaths;
1267a0261a43SJames C. McPherson 	rv = ioctl(vhci_fd, SCSI_VHCI_GET_CLIENT_MULTIPATH_INFO, &ioc);
1268a0261a43SJames C. McPherson 	if (rv || npaths == 0) {
1269a0261a43SJames C. McPherson 		logmsg(MSG_INFO,
1270a0261a43SJames C. McPherson 		    "SCSI_VHCI_GET_CLIENT_MULTIPATH_INFO ioctl() failed, "
1271a0261a43SJames C. McPherson 		    "%s (%d)\n", strerror(rv), rv);
1272a0261a43SJames C. McPherson 		goto failure;
12735a4c37c9Sqh201292 	}
12745a4c37c9Sqh201292 
12755a4c37c9Sqh201292 	bzero(&ioc, sizeof (sv_iocdata_t));
1276a0261a43SJames C. McPherson 	ioc.client = devpath;
12775a4c37c9Sqh201292 	ioc.buf_elem = npaths;
12785a4c37c9Sqh201292 	ioc.ret_elem = &npaths;
1279a0261a43SJames C. McPherson 	if ((ioc.ret_buf = calloc(npaths, sizeof (sv_path_info_t)))
1280a0261a43SJames C. McPherson 	    == NULL)
1281a0261a43SJames C. McPherson 		goto failure;
1282a0261a43SJames C. McPherson 	rv = ioctl(vhci_fd, SCSI_VHCI_GET_CLIENT_MULTIPATH_INFO, &ioc);
1283a0261a43SJames C. McPherson 	if (rv || npaths == 0) {
1284a0261a43SJames C. McPherson 		logmsg(MSG_INFO,
1285a0261a43SJames C. McPherson 		    "SCSI_VHCI_GET_CLIENT_MULTIPATH_INFO ioctl() (#2) "
1286a0261a43SJames C. McPherson 		    "failed, %s (%d)\n", strerror(rv), rv);
1287a0261a43SJames C. McPherson 		goto failure;
12885a4c37c9Sqh201292 	}
12895a4c37c9Sqh201292 
12905a4c37c9Sqh201292 	if (ioc.buf_elem < npaths)
12915a4c37c9Sqh201292 		npaths = ioc.buf_elem;
12925a4c37c9Sqh201292 
12935a4c37c9Sqh201292 	pi = (sv_path_info_t *)ioc.ret_buf;
12945a4c37c9Sqh201292 	while (npaths--) {
1295a0261a43SJames C. McPherson 		if (pi->ret_state == MDI_PATHINFO_STATE_ONLINE) {
12965b504601Sjiang wu - Sun Microsystems - Beijing China 			char nodename[5];
12975b504601Sjiang wu - Sun Microsystems - Beijing China 			char *phci_driver = NULL;
1298a0261a43SJames C. McPherson 
12995b504601Sjiang wu - Sun Microsystems - Beijing China 			bzero(nodename, 5);
13005b504601Sjiang wu - Sun Microsystems - Beijing China 			phci_driver = malloc(10);
13015b504601Sjiang wu - Sun Microsystems - Beijing China 			if (phci_driver == NULL) {
13025b504601Sjiang wu - Sun Microsystems - Beijing China 				logmsg(MSG_INFO,
13035b504601Sjiang wu - Sun Microsystems - Beijing China 				    "vhci_to_phci: Memory allocation failed\n");
13045b504601Sjiang wu - Sun Microsystems - Beijing China 				goto failure;
13055b504601Sjiang wu - Sun Microsystems - Beijing China 			}
13065b504601Sjiang wu - Sun Microsystems - Beijing China 			bzero(phci_driver, 10);
13075b504601Sjiang wu - Sun Microsystems - Beijing China 			get_phci_driver_name(pi->device.ret_phci,
13085b504601Sjiang wu - Sun Microsystems - Beijing China 			    &phci_driver);
13095b504601Sjiang wu - Sun Microsystems - Beijing China 			logmsg(MSG_INFO, "phci driver name: %s\n", phci_driver);
13105b504601Sjiang wu - Sun Microsystems - Beijing China 			/*
13115b504601Sjiang wu - Sun Microsystems - Beijing China 			 * A hack, but nicer than a platform-specific ifdef
13125b504601Sjiang wu - Sun Microsystems - Beijing China 			 * fp on SPARC using "ssd" as nodename
13135b504601Sjiang wu - Sun Microsystems - Beijing China 			 * mpt use "sd" when mpxio disabled, use "disk" when
13145b504601Sjiang wu - Sun Microsystems - Beijing China 			 * mpxio is enabled
13155b504601Sjiang wu - Sun Microsystems - Beijing China 			 * for alll other cases, "disk" should be used as the
13165b504601Sjiang wu - Sun Microsystems - Beijing China 			 * nodename
13175b504601Sjiang wu - Sun Microsystems - Beijing China 			 */
1318a0261a43SJames C. McPherson 			if (strstr(devpath, "ssd") != NULL) {
13195b504601Sjiang wu - Sun Microsystems - Beijing China 				(void) snprintf(nodename, 5, "ssd");
13205b504601Sjiang wu - Sun Microsystems - Beijing China 			} else if (strncmp(phci_driver, "mpt", 10) == 0) {
13215b504601Sjiang wu - Sun Microsystems - Beijing China 				(void) snprintf(nodename, 5, "sd");
1322a0261a43SJames C. McPherson 			} else {
13235b504601Sjiang wu - Sun Microsystems - Beijing China 				(void) snprintf(nodename, 5, "disk");
1324a0261a43SJames C. McPherson 			}
1325a0261a43SJames C. McPherson 			(void) snprintf(physpath, MAXPATHLEN, "%s/%s@%s",
1326a0261a43SJames C. McPherson 			    pi->device.ret_phci, nodename, pi->ret_addr);
13275a4c37c9Sqh201292 			free(ioc.ret_buf);
13285b504601Sjiang wu - Sun Microsystems - Beijing China 			free(phci_driver);
1329a0261a43SJames C. McPherson 			return;
13305a4c37c9Sqh201292 		}
13315a4c37c9Sqh201292 		pi++;
13325a4c37c9Sqh201292 	}
13335a4c37c9Sqh201292 
1334a0261a43SJames C. McPherson failure:
1335a0261a43SJames C. McPherson 	(void) snprintf(physpath, MAXPATHLEN, "NOT_MAPPED");
13365a4c37c9Sqh201292 }
13375a4c37c9Sqh201292 
13385a4c37c9Sqh201292 /*
1339a0261a43SJames C. McPherson  * Write /etc/vfstab to /etc/vfstab.new, with any remapped device
1340a0261a43SJames C. McPherson  * names substituted.
13417c478bd9Sstevel@tonic-gate  *
13427c478bd9Sstevel@tonic-gate  * Returns:
1343a0261a43SJames C. McPherson  *	0	successful operation
13447c478bd9Sstevel@tonic-gate  *	-1	failed
13457c478bd9Sstevel@tonic-gate  */
13467c478bd9Sstevel@tonic-gate static int
1347a0261a43SJames C. McPherson update_vfstab()
13487c478bd9Sstevel@tonic-gate {
1349a0261a43SJames C. McPherson 	FILE *fdin, *fdout;
13507c478bd9Sstevel@tonic-gate 	char *buf, *tmpbuf;
1351a0261a43SJames C. McPherson 	char fname[MAXPATHLEN];
1352a0261a43SJames C. McPherson 	int rv = -1, rval = -1;
13537c478bd9Sstevel@tonic-gate 	char cdev[MAXPATHLEN];
13547c478bd9Sstevel@tonic-gate 	char bdev[MAXPATHLEN];
13557c478bd9Sstevel@tonic-gate 	char mntpt[MAXPATHLEN];
13567c478bd9Sstevel@tonic-gate 	char fstype[512];
13577c478bd9Sstevel@tonic-gate 	char fsckpass[512];
13587c478bd9Sstevel@tonic-gate 	char mntboot[512];
1359a0261a43SJames C. McPherson 	char mntopt[MAXPATHLEN];
13607c478bd9Sstevel@tonic-gate 	char fmt[80];
1361a0261a43SJames C. McPherson 	char *prefixt = NULL;
1362a0261a43SJames C. McPherson 	char *curdev = NULL;
1363a0261a43SJames C. McPherson 	char *thisdevid = NULL;
1364a0261a43SJames C. McPherson 	char *slice = NULL;
1365a0261a43SJames C. McPherson 	nvlist_t *thisdev;
1366a0261a43SJames C. McPherson 	boolean_t devmpx = B_FALSE;
13677c478bd9Sstevel@tonic-gate 
1368a0261a43SJames C. McPherson 	buf = calloc(1, MAXPATHLEN);
1369a0261a43SJames C. McPherson 	tmpbuf = calloc(1, MAXPATHLEN);
1370a0261a43SJames C. McPherson 	if (buf == NULL || tmpbuf == NULL)
13717c478bd9Sstevel@tonic-gate 		return (-1);
13727c478bd9Sstevel@tonic-gate 
1373a0261a43SJames C. McPherson 	(void) snprintf(fname, MAXPATHLEN, "/etc/mpxio/vfstab.new");
1374a0261a43SJames C. McPherson 
1375a0261a43SJames C. McPherson 	fdin = fopen("/etc/vfstab", "r");
1376a0261a43SJames C. McPherson 	fdout = fopen(fname, "w+");
1377a0261a43SJames C. McPherson 	if (fdin == NULL || fdout == NULL) {
1378a0261a43SJames C. McPherson 		logmsg(MSG_INFO, "Unable to open vfstab or create a backup "
1379a0261a43SJames C. McPherson 		    "vfstab %s\n");
1380a0261a43SJames C. McPherson 		return (-1);
1381a0261a43SJames C. McPherson 	}
13827c478bd9Sstevel@tonic-gate 
13837c478bd9Sstevel@tonic-gate 	(void) snprintf(fmt, sizeof (fmt),
13847c478bd9Sstevel@tonic-gate 	    "%%%ds %%%ds %%%ds %%%ds %%%ds %%%ds %%%ds", sizeof (bdev) - 1,
13857c478bd9Sstevel@tonic-gate 	    sizeof (cdev) - 1, sizeof (mntpt) - 1, sizeof (fstype) - 1,
13867c478bd9Sstevel@tonic-gate 	    sizeof (fsckpass) - 1, sizeof (mntboot) - 1, sizeof (mntopt) - 1);
13877c478bd9Sstevel@tonic-gate 
1388a0261a43SJames C. McPherson 	while (fgets(buf, MAXPATHLEN, fdin) != NULL) {
1389a0261a43SJames C. McPherson 		if (strlen(buf) == (MAXPATHLEN - 1) &&
1390a0261a43SJames C. McPherson 		    buf[MAXPATHLEN-2] != '\n') {
1391a0261a43SJames C. McPherson 			logmsg(MSG_ERROR,
1392a0261a43SJames C. McPherson 			    gettext("/etc/vfstab line length too long, "
13937c478bd9Sstevel@tonic-gate 			    "exceeded %2$d: \"%3$s\"\n"),
1394a0261a43SJames C. McPherson 			    MAXPATHLEN - 2, buf);
13957c478bd9Sstevel@tonic-gate 			goto out;
13967c478bd9Sstevel@tonic-gate 		}
13977c478bd9Sstevel@tonic-gate 
1398a0261a43SJames C. McPherson 		prefixt = NULL;
1399a0261a43SJames C. McPherson 		curdev = NULL;
1400a0261a43SJames C. McPherson 		slice = NULL;
1401a0261a43SJames C. McPherson 		thisdevid = NULL;
1402a0261a43SJames C. McPherson 		thisdev = NULL;
14037c478bd9Sstevel@tonic-gate 
1404a0261a43SJames C. McPherson 		/* LINTED - variable format specifier */
1405a0261a43SJames C. McPherson 		rv = sscanf(buf, fmt, bdev, cdev, mntpt, fstype, fsckpass,
1406a0261a43SJames C. McPherson 		    mntboot, mntopt);
14077c478bd9Sstevel@tonic-gate 
14087c478bd9Sstevel@tonic-gate 		/*
1409a0261a43SJames C. McPherson 		 * Walk through the lines in the input file (/etc/vfstab),
1410a0261a43SJames C. McPherson 		 * skipping anything which is _not_ a COGD (common or garden
1411a0261a43SJames C. McPherson 		 * disk), ie all the /devices, /system, /dev/md, /dev/vx and
1412a0261a43SJames C. McPherson 		 * /dev/zvol and so forth.
14137c478bd9Sstevel@tonic-gate 		 */
1414a0261a43SJames C. McPherson 		if ((rv == 7) && (bdev[0] == '/') &&
1415a0261a43SJames C. McPherson 		    (strstr(bdev, "/dev/dsk"))) {
1416a0261a43SJames C. McPherson 			slice = strrchr(bdev, 's');
1417a0261a43SJames C. McPherson 			/* take a copy, strip off /dev/dsk/ */
1418a0261a43SJames C. McPherson 			prefixt = strrchr(bdev, 'c');
1419a0261a43SJames C. McPherson 			prefixt[strlen(bdev) - 9 - strlen(slice)] = '\0';
1420a0261a43SJames C. McPherson 			slice++; /* advance past the s */
1421a0261a43SJames C. McPherson 			rval = nvlist_lookup_string(mapnvl, prefixt,
1422a0261a43SJames C. McPherson 			    &thisdevid);
1423a0261a43SJames C. McPherson 			if (rval) {
1424a0261a43SJames C. McPherson 				/* Whoa, where did this device go?! */
1425a0261a43SJames C. McPherson 				logmsg(MSG_INFO,
1426a0261a43SJames C. McPherson 				    "error looking up device %s\n", prefixt);
1427a0261a43SJames C. McPherson 				/* Comment-out this line in the new version */
1428a0261a43SJames C. McPherson 				(void) snprintf(tmpbuf, MAXPATHLEN,
1429a0261a43SJames C. McPherson 				    "# DEVICE NOT FOUND %s", buf);
1430a0261a43SJames C. McPherson 				(void) fprintf(fdout, "%s", tmpbuf);
1431a0261a43SJames C. McPherson 				continue;
1432a0261a43SJames C. McPherson 			} else {
1433a0261a43SJames C. McPherson 				/* The device exists in our mapnvl */
1434a0261a43SJames C. McPherson 				(void) nvlist_lookup_nvlist(mapnvl, thisdevid,
1435a0261a43SJames C. McPherson 				    &thisdev);
1436a0261a43SJames C. McPherson 				(void) nvlist_lookup_boolean_value(thisdev,
1437a0261a43SJames C. McPherson 				    NVL_MPXEN, &devmpx);
1438a0261a43SJames C. McPherson 				(void) nvlist_lookup_string(thisdev,
1439a0261a43SJames C. McPherson 				    ((devmpx == B_TRUE)
1440a0261a43SJames C. McPherson 				    ? NVL_MPXPATH : NVL_PATH),
1441a0261a43SJames C. McPherson 				    &curdev);
1442a0261a43SJames C. McPherson 			}
14437c478bd9Sstevel@tonic-gate 		}
14447c478bd9Sstevel@tonic-gate 
1445a0261a43SJames C. McPherson 		if ((prefixt != NULL) && (curdev != NULL) &&
1446a0261a43SJames C. McPherson 		    (rv = (strncmp(prefixt, curdev, strlen(prefixt)) != 0))) {
1447a0261a43SJames C. McPherson 			/* Mapping change for this device */
1448a0261a43SJames C. McPherson 			if (strcmp(fstype, "swap") == 0) {
1449a0261a43SJames C. McPherson 				(void) snprintf(tmpbuf, MAXPATHLEN,
1450a0261a43SJames C. McPherson 				    "/dev/dsk/%ss%s\t-\t-\tswap\t"
1451a0261a43SJames C. McPherson 				    "%s\t%s\t%s\n",
1452a0261a43SJames C. McPherson 				    curdev, slice, fsckpass, mntboot, mntopt);
1453a0261a43SJames C. McPherson 			} else {
1454a0261a43SJames C. McPherson 				(void) snprintf(tmpbuf, MAXPATHLEN,
1455a0261a43SJames C. McPherson 				    "/dev/dsk/%ss%s\t/dev/rdsk/%ss%s\t"
1456a0261a43SJames C. McPherson 				    "%s\t%s\t%s\t%s\t%s\n",
1457a0261a43SJames C. McPherson 				    curdev, slice, curdev, slice,
1458a0261a43SJames C. McPherson 				    mntpt, fstype, fsckpass, mntboot, mntopt);
1459a0261a43SJames C. McPherson 			}
1460a0261a43SJames C. McPherson 			errno = 0;
1461a0261a43SJames C. McPherson 			(void) fprintf(fdout, "%s", tmpbuf);
1462a0261a43SJames C. McPherson 		} else {
1463a0261a43SJames C. McPherson 			(void) fprintf(fdout, "%s", buf);
1464a0261a43SJames C. McPherson 		}
1465a0261a43SJames C. McPherson 
1466a0261a43SJames C. McPherson 		errno = 0;
1467a0261a43SJames C. McPherson 		if (fflush(fdout) != 0) {
1468a0261a43SJames C. McPherson 			logmsg(MSG_ERROR,
1469a0261a43SJames C. McPherson 			    gettext("fprintf failed to write to %s: %s (%d)\n"),
1470a0261a43SJames C. McPherson 			    fname, strerror(errno), errno);
14717c478bd9Sstevel@tonic-gate 			goto out;
14727c478bd9Sstevel@tonic-gate 		}
14737c478bd9Sstevel@tonic-gate 	}
14747c478bd9Sstevel@tonic-gate out:
1475a0261a43SJames C. McPherson 	(void) fclose(fdin);
1476a0261a43SJames C. McPherson 	(void) fclose(fdout);
14777c478bd9Sstevel@tonic-gate 	free(buf);
14787c478bd9Sstevel@tonic-gate 	free(tmpbuf);
1479a0261a43SJames C. McPherson 	return (errno);
14808cecff49Sgp87344 }
1481