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
518c2aff7Sartem  * Common Development and Distribution License (the "License").
618c2aff7Sartem  * 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  */
217c478bd9Sstevel@tonic-gate /*
22*2174cb7bSVirginia Wray  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate #include <fcntl.h>
277c478bd9Sstevel@tonic-gate #include <libdevinfo.h>
287c478bd9Sstevel@tonic-gate #include <stdio.h>
297c478bd9Sstevel@tonic-gate #include <stdlib.h>
307c478bd9Sstevel@tonic-gate #include <string.h>
317c478bd9Sstevel@tonic-gate #include <sys/sunddi.h>
327c478bd9Sstevel@tonic-gate #include <sys/types.h>
337c478bd9Sstevel@tonic-gate #include <sys/stat.h>
347c478bd9Sstevel@tonic-gate #include <dirent.h>
357c478bd9Sstevel@tonic-gate #include <unistd.h>
367c478bd9Sstevel@tonic-gate #include <sys/dkio.h>
377c478bd9Sstevel@tonic-gate 
38*2174cb7bSVirginia Wray #if defined(i386) || defined(__amd64)
39*2174cb7bSVirginia Wray #include <sys/dktp/fdisk.h>
40*2174cb7bSVirginia Wray #include <libfdisk.h>
41*2174cb7bSVirginia Wray #endif
42*2174cb7bSVirginia Wray 
437c478bd9Sstevel@tonic-gate #include "libdiskmgt.h"
447c478bd9Sstevel@tonic-gate #include "disks_private.h"
457c478bd9Sstevel@tonic-gate #include "partition.h"
467c478bd9Sstevel@tonic-gate 
477c478bd9Sstevel@tonic-gate #ifdef sparc
487c478bd9Sstevel@tonic-gate #define	les(val)	((((val)&0xFF)<<8)|(((val)>>8)&0xFF))
497c478bd9Sstevel@tonic-gate #define	lel(val)	(((unsigned)(les((val)&0x0000FFFF))<<16) | \
507c478bd9Sstevel@tonic-gate 			    (les((unsigned)((val)&0xffff0000)>>16)))
517c478bd9Sstevel@tonic-gate #else
527c478bd9Sstevel@tonic-gate #define	les(val)	(val)
537c478bd9Sstevel@tonic-gate #define	lel(val)	(val)
547c478bd9Sstevel@tonic-gate #endif
557c478bd9Sstevel@tonic-gate 
56*2174cb7bSVirginia Wray #define	TOTAL_NUMPART	(FD_NUMPART + MAX_EXT_PARTS)
57*2174cb7bSVirginia Wray 
587c478bd9Sstevel@tonic-gate #define	ISIZE		FD_NUMPART * sizeof (struct ipart)
597c478bd9Sstevel@tonic-gate 
607c478bd9Sstevel@tonic-gate static int	desc_ok(descriptor_t *dp);
617c478bd9Sstevel@tonic-gate static int	get_attrs(descriptor_t *dp, struct ipart *iparts,
627c478bd9Sstevel@tonic-gate 		    nvlist_t *attrs);
637c478bd9Sstevel@tonic-gate static int	get_parts(disk_t *disk, struct ipart *iparts, char *opath,
647c478bd9Sstevel@tonic-gate 		    int opath_len);
657c478bd9Sstevel@tonic-gate static int	open_disk(disk_t *diskp, char *opath, int len);
667c478bd9Sstevel@tonic-gate static int	has_slices(descriptor_t *desc, int *errp);
677c478bd9Sstevel@tonic-gate 
687c478bd9Sstevel@tonic-gate descriptor_t **
697c478bd9Sstevel@tonic-gate partition_get_assoc_descriptors(descriptor_t *desc, dm_desc_type_t type,
707c478bd9Sstevel@tonic-gate     int *errp)
717c478bd9Sstevel@tonic-gate {
727c478bd9Sstevel@tonic-gate 	if (!desc_ok(desc)) {
73*2174cb7bSVirginia Wray 		*errp = ENODEV;
74*2174cb7bSVirginia Wray 		return (NULL);
757c478bd9Sstevel@tonic-gate 	}
767c478bd9Sstevel@tonic-gate 
777c478bd9Sstevel@tonic-gate 	switch (type) {
787c478bd9Sstevel@tonic-gate 	case DM_MEDIA:
79*2174cb7bSVirginia Wray 		return (media_get_assocs(desc, errp));
807c478bd9Sstevel@tonic-gate 	case DM_SLICE:
81*2174cb7bSVirginia Wray 		if (!has_slices(desc, errp)) {
82*2174cb7bSVirginia Wray 			if (*errp != 0) {
83*2174cb7bSVirginia Wray 				return (NULL);
84*2174cb7bSVirginia Wray 			}
85*2174cb7bSVirginia Wray 			return (libdiskmgt_empty_desc_array(errp));
867c478bd9Sstevel@tonic-gate 		}
87*2174cb7bSVirginia Wray 		return (slice_get_assocs(desc, errp));
887c478bd9Sstevel@tonic-gate 	}
897c478bd9Sstevel@tonic-gate 
907c478bd9Sstevel@tonic-gate 	*errp = EINVAL;
917c478bd9Sstevel@tonic-gate 	return (NULL);
927c478bd9Sstevel@tonic-gate }
937c478bd9Sstevel@tonic-gate 
947c478bd9Sstevel@tonic-gate /*
957c478bd9Sstevel@tonic-gate  * This is called by media/slice to get the associated partitions.
967c478bd9Sstevel@tonic-gate  * For a media desc. we just get all the partitions, but for a slice desc.
977c478bd9Sstevel@tonic-gate  * we just get the active solaris partition.
987c478bd9Sstevel@tonic-gate  */
997c478bd9Sstevel@tonic-gate descriptor_t **
1007c478bd9Sstevel@tonic-gate partition_get_assocs(descriptor_t *desc, int *errp)
1017c478bd9Sstevel@tonic-gate {
1027c478bd9Sstevel@tonic-gate 	descriptor_t	**partitions;
1037c478bd9Sstevel@tonic-gate 	int		pos;
1047c478bd9Sstevel@tonic-gate 	int		i;
105*2174cb7bSVirginia Wray 	struct ipart	iparts[TOTAL_NUMPART];
1067c478bd9Sstevel@tonic-gate 	char		pname[MAXPATHLEN];
1077c478bd9Sstevel@tonic-gate 	int		conv_flag = 0;
1083e1bd7a2Ssjelinek #if defined(i386) || defined(__amd64)
1093e1bd7a2Ssjelinek 	int		len;
1103e1bd7a2Ssjelinek #endif
1117c478bd9Sstevel@tonic-gate 
1127c478bd9Sstevel@tonic-gate 	if (get_parts(desc->p.disk, iparts, pname, sizeof (pname)) != 0) {
113*2174cb7bSVirginia Wray 		return (libdiskmgt_empty_desc_array(errp));
1147c478bd9Sstevel@tonic-gate 	}
1157c478bd9Sstevel@tonic-gate 
1167c478bd9Sstevel@tonic-gate 	/* allocate the array for the descriptors */
117*2174cb7bSVirginia Wray 	partitions = (descriptor_t **)calloc(TOTAL_NUMPART + 1,
1187c478bd9Sstevel@tonic-gate 	    sizeof (descriptor_t *));
1197c478bd9Sstevel@tonic-gate 	if (partitions == NULL) {
120*2174cb7bSVirginia Wray 		*errp = ENOMEM;
121*2174cb7bSVirginia Wray 		return (NULL);
1227c478bd9Sstevel@tonic-gate 	}
1237c478bd9Sstevel@tonic-gate 
1243e1bd7a2Ssjelinek #if defined(i386) || defined(__amd64)
125*2174cb7bSVirginia Wray 	/* convert part. name (e.g. c0d0p1) */
126*2174cb7bSVirginia Wray 	len = strlen(pname);
127*2174cb7bSVirginia Wray 	if (len > 1 && *(pname + (len - 2)) == 'p') {
1287c478bd9Sstevel@tonic-gate 		conv_flag = 1;
1297c478bd9Sstevel@tonic-gate 		*(pname + (len - 1)) = 0;
130*2174cb7bSVirginia Wray 	}
1317c478bd9Sstevel@tonic-gate #endif
1327c478bd9Sstevel@tonic-gate 
1337c478bd9Sstevel@tonic-gate 	/*
1347c478bd9Sstevel@tonic-gate 	 * If this is a slice desc. we need the first active solaris partition
1357c478bd9Sstevel@tonic-gate 	 * and if there isn't one then we need the first solaris partition.
1367c478bd9Sstevel@tonic-gate 	 */
1377c478bd9Sstevel@tonic-gate 	if (desc->type == DM_SLICE) {
138*2174cb7bSVirginia Wray 		for (i = 0; i < TOTAL_NUMPART; i++) {
139*2174cb7bSVirginia Wray 			if (iparts[i].bootid == ACTIVE &&
140*2174cb7bSVirginia Wray 			    (iparts[i].systid == SUNIXOS ||
141*2174cb7bSVirginia Wray 			    iparts[i].systid == SUNIXOS2)) {
142*2174cb7bSVirginia Wray 				break;
143*2174cb7bSVirginia Wray 			}
1447c478bd9Sstevel@tonic-gate 		}
145*2174cb7bSVirginia Wray 
146*2174cb7bSVirginia Wray 		/*
147*2174cb7bSVirginia Wray 		 * no active solaris part.,*try to get the first solaris part.
148*2174cb7bSVirginia Wray 		 */
149*2174cb7bSVirginia Wray 		if (i >= TOTAL_NUMPART) {
150*2174cb7bSVirginia Wray 			for (i = 0; i < TOTAL_NUMPART; i++) {
151*2174cb7bSVirginia Wray 				if (iparts[i].systid == SUNIXOS ||
152*2174cb7bSVirginia Wray 				    iparts[i].systid == SUNIXOS2) {
153*2174cb7bSVirginia Wray 					break;
154*2174cb7bSVirginia Wray 				}
155*2174cb7bSVirginia Wray 			}
1567c478bd9Sstevel@tonic-gate 		}
1577c478bd9Sstevel@tonic-gate 
158*2174cb7bSVirginia Wray 		if (i < TOTAL_NUMPART) {
1597c478bd9Sstevel@tonic-gate 		/* we found a solaris partition to use */
160*2174cb7bSVirginia Wray 			char	part_name[MAXPATHLEN];
1617c478bd9Sstevel@tonic-gate 
162*2174cb7bSVirginia Wray 			if (conv_flag) {
163*2174cb7bSVirginia Wray 			/* convert part. name (e.g. c0d0p1) */
164*2174cb7bSVirginia Wray 				(void) snprintf(part_name, sizeof (part_name),
165*2174cb7bSVirginia Wray 				    "%s%d", pname, i+1);
166*2174cb7bSVirginia Wray 			} else {
167*2174cb7bSVirginia Wray 				(void) snprintf(part_name, sizeof (part_name),
168*2174cb7bSVirginia Wray 				    "%d", i+1);
169*2174cb7bSVirginia Wray 			}
1707c478bd9Sstevel@tonic-gate 
171*2174cb7bSVirginia Wray 			/* the media name comes from the slice desc. */
172*2174cb7bSVirginia Wray 			partitions[0] = cache_get_desc(DM_PARTITION,
173*2174cb7bSVirginia Wray 			    desc->p.disk, part_name, desc->secondary_name,
174*2174cb7bSVirginia Wray 			    errp);
175*2174cb7bSVirginia Wray 			if (*errp != 0) {
176*2174cb7bSVirginia Wray 				cache_free_descriptors(partitions);
177*2174cb7bSVirginia Wray 				return (NULL);
178*2174cb7bSVirginia Wray 			}
179*2174cb7bSVirginia Wray 			partitions[1] = NULL;
1807c478bd9Sstevel@tonic-gate 
181*2174cb7bSVirginia Wray 			return (partitions);
182*2174cb7bSVirginia Wray 		}
1837c478bd9Sstevel@tonic-gate 
184*2174cb7bSVirginia Wray 		return (libdiskmgt_empty_desc_array(errp));
1857c478bd9Sstevel@tonic-gate 	}
1867c478bd9Sstevel@tonic-gate 
1877c478bd9Sstevel@tonic-gate 	/* Must be for media, so get all the parts. */
1887c478bd9Sstevel@tonic-gate 
1897c478bd9Sstevel@tonic-gate 	pos = 0;
190*2174cb7bSVirginia Wray 	for (i = 0; i < TOTAL_NUMPART; i++) {
191*2174cb7bSVirginia Wray 		if (iparts[i].systid != UNUSED) {
192*2174cb7bSVirginia Wray 			char	part_name[MAXPATHLEN];
1937c478bd9Sstevel@tonic-gate 
194*2174cb7bSVirginia Wray 			/*
195*2174cb7bSVirginia Wray 			 * Process the descriptors and modify the cxdxpx
196*2174cb7bSVirginia Wray 			 * format so that it refers to the fdisk partition
197*2174cb7bSVirginia Wray 			 * number and not to the physical disk. This is
198*2174cb7bSVirginia Wray 			 * achieved by i+1, where i is the number of the
199*2174cb7bSVirginia Wray 			 * physical disk partition.
200*2174cb7bSVirginia Wray 			 */
201*2174cb7bSVirginia Wray 			if (conv_flag) {
202*2174cb7bSVirginia Wray 				/* convert part. name (e.g. c0d0p1) */
203*2174cb7bSVirginia Wray 				(void) snprintf(part_name, sizeof (part_name),
204*2174cb7bSVirginia Wray 				    "%s%d", pname, i+1);
205*2174cb7bSVirginia Wray 			} else {
206*2174cb7bSVirginia Wray 				(void) snprintf(part_name, sizeof (part_name),
207*2174cb7bSVirginia Wray 				    "%d", i+1);
208*2174cb7bSVirginia Wray 			}
2097c478bd9Sstevel@tonic-gate 
210*2174cb7bSVirginia Wray 			/* the media name comes from the media desc. */
211*2174cb7bSVirginia Wray 			partitions[pos] = cache_get_desc(DM_PARTITION,
212*2174cb7bSVirginia Wray 			    desc->p.disk, part_name, desc->name, errp);
213*2174cb7bSVirginia Wray 			if (*errp != 0) {
214*2174cb7bSVirginia Wray 				cache_free_descriptors(partitions);
215*2174cb7bSVirginia Wray 				return (NULL);
216*2174cb7bSVirginia Wray 			}
2177c478bd9Sstevel@tonic-gate 
218*2174cb7bSVirginia Wray 			pos++;
219*2174cb7bSVirginia Wray 		}
2207c478bd9Sstevel@tonic-gate 	}
2217c478bd9Sstevel@tonic-gate 	partitions[pos] = NULL;
2227c478bd9Sstevel@tonic-gate 
2237c478bd9Sstevel@tonic-gate 	*errp = 0;
2247c478bd9Sstevel@tonic-gate 	return (partitions);
2257c478bd9Sstevel@tonic-gate }
2267c478bd9Sstevel@tonic-gate 
2277c478bd9Sstevel@tonic-gate nvlist_t *
2287c478bd9Sstevel@tonic-gate partition_get_attributes(descriptor_t *dp, int *errp)
2297c478bd9Sstevel@tonic-gate {
2307c478bd9Sstevel@tonic-gate 	nvlist_t	*attrs = NULL;
231*2174cb7bSVirginia Wray 	struct ipart	iparts[TOTAL_NUMPART];
2327c478bd9Sstevel@tonic-gate 
2337c478bd9Sstevel@tonic-gate 	if (!desc_ok(dp)) {
234*2174cb7bSVirginia Wray 		*errp = ENODEV;
235*2174cb7bSVirginia Wray 		return (NULL);
2367c478bd9Sstevel@tonic-gate 	}
2377c478bd9Sstevel@tonic-gate 
2387c478bd9Sstevel@tonic-gate 	if ((*errp = get_parts(dp->p.disk, iparts, NULL, 0)) != 0) {
239*2174cb7bSVirginia Wray 		return (NULL);
2407c478bd9Sstevel@tonic-gate 	}
2417c478bd9Sstevel@tonic-gate 
2427c478bd9Sstevel@tonic-gate 	if (nvlist_alloc(&attrs, NVATTRS, 0) != 0) {
243*2174cb7bSVirginia Wray 		*errp = ENOMEM;
244*2174cb7bSVirginia Wray 		return (NULL);
2457c478bd9Sstevel@tonic-gate 	}
2467c478bd9Sstevel@tonic-gate 
2477c478bd9Sstevel@tonic-gate 	if ((*errp = get_attrs(dp, iparts, attrs)) != 0) {
248*2174cb7bSVirginia Wray 		nvlist_free(attrs);
249*2174cb7bSVirginia Wray 		attrs = NULL;
2507c478bd9Sstevel@tonic-gate 	}
2517c478bd9Sstevel@tonic-gate 
2527c478bd9Sstevel@tonic-gate 	return (attrs);
2537c478bd9Sstevel@tonic-gate }
2547c478bd9Sstevel@tonic-gate 
2557c478bd9Sstevel@tonic-gate /*
2567c478bd9Sstevel@tonic-gate  * Look for the partition by the partition number (which is not too useful).
2577c478bd9Sstevel@tonic-gate  */
2587c478bd9Sstevel@tonic-gate descriptor_t *
2597c478bd9Sstevel@tonic-gate partition_get_descriptor_by_name(char *name, int *errp)
2607c478bd9Sstevel@tonic-gate {
2617c478bd9Sstevel@tonic-gate 	descriptor_t	**partitions;
2627c478bd9Sstevel@tonic-gate 	int		i;
2637c478bd9Sstevel@tonic-gate 	descriptor_t	*partition = NULL;
2647c478bd9Sstevel@tonic-gate 
2657c478bd9Sstevel@tonic-gate 	partitions = cache_get_descriptors(DM_PARTITION, errp);
2667c478bd9Sstevel@tonic-gate 	if (*errp != 0) {
267*2174cb7bSVirginia Wray 		return (NULL);
2687c478bd9Sstevel@tonic-gate 	}
2697c478bd9Sstevel@tonic-gate 
2707c478bd9Sstevel@tonic-gate 	for (i = 0; partitions[i]; i++) {
271*2174cb7bSVirginia Wray 		if (libdiskmgt_str_eq(name, partitions[i]->name)) {
272*2174cb7bSVirginia Wray 			partition = partitions[i];
273*2174cb7bSVirginia Wray 		} else {
274*2174cb7bSVirginia Wray 			/* clean up the unused descriptors */
275*2174cb7bSVirginia Wray 			cache_free_descriptor(partitions[i]);
276*2174cb7bSVirginia Wray 		}
2777c478bd9Sstevel@tonic-gate 	}
2787c478bd9Sstevel@tonic-gate 	free(partitions);
2797c478bd9Sstevel@tonic-gate 
2807c478bd9Sstevel@tonic-gate 	if (partition == NULL) {
281*2174cb7bSVirginia Wray 		*errp = ENODEV;
2827c478bd9Sstevel@tonic-gate 	}
2837c478bd9Sstevel@tonic-gate 
2847c478bd9Sstevel@tonic-gate 	return (partition);
2857c478bd9Sstevel@tonic-gate }
2867c478bd9Sstevel@tonic-gate 
2877c478bd9Sstevel@tonic-gate /* ARGSUSED */
2887c478bd9Sstevel@tonic-gate descriptor_t **
2897c478bd9Sstevel@tonic-gate partition_get_descriptors(int filter[], int *errp)
2907c478bd9Sstevel@tonic-gate {
2917c478bd9Sstevel@tonic-gate 	return (cache_get_descriptors(DM_PARTITION, errp));
2927c478bd9Sstevel@tonic-gate }
2937c478bd9Sstevel@tonic-gate 
2947c478bd9Sstevel@tonic-gate char *
2957c478bd9Sstevel@tonic-gate partition_get_name(descriptor_t *desc)
2967c478bd9Sstevel@tonic-gate {
2977c478bd9Sstevel@tonic-gate 	return (desc->name);
2987c478bd9Sstevel@tonic-gate }
2997c478bd9Sstevel@tonic-gate 
3007c478bd9Sstevel@tonic-gate /* ARGSUSED */
3017c478bd9Sstevel@tonic-gate nvlist_t *
3027c478bd9Sstevel@tonic-gate partition_get_stats(descriptor_t *dp, int stat_type, int *errp)
3037c478bd9Sstevel@tonic-gate {
3047c478bd9Sstevel@tonic-gate 	/* There are no stat types defined for partitions */
3057c478bd9Sstevel@tonic-gate 	*errp = EINVAL;
3067c478bd9Sstevel@tonic-gate 	return (NULL);
3077c478bd9Sstevel@tonic-gate }
3087c478bd9Sstevel@tonic-gate 
3097c478bd9Sstevel@tonic-gate /* ARGSUSED */
3107c478bd9Sstevel@tonic-gate int
3117c478bd9Sstevel@tonic-gate partition_has_fdisk(disk_t *dp, int fd)
3127c478bd9Sstevel@tonic-gate {
3137c478bd9Sstevel@tonic-gate 	char		bootsect[512 * 3]; /* 3 sectors to be safe */
3147c478bd9Sstevel@tonic-gate 
3157c478bd9Sstevel@tonic-gate #ifdef sparc
3167c478bd9Sstevel@tonic-gate 	if (dp->drv_type == DM_DT_FIXED) {
317*2174cb7bSVirginia Wray 		/* on sparc, only removable media can have fdisk parts. */
318*2174cb7bSVirginia Wray 		return (0);
3197c478bd9Sstevel@tonic-gate 	}
3207c478bd9Sstevel@tonic-gate #endif
3217c478bd9Sstevel@tonic-gate 
3227c478bd9Sstevel@tonic-gate 	/*
3237c478bd9Sstevel@tonic-gate 	 * We assume the caller already made sure media was inserted and
3247c478bd9Sstevel@tonic-gate 	 * spun up.
3257c478bd9Sstevel@tonic-gate 	 */
3267c478bd9Sstevel@tonic-gate 
3277c478bd9Sstevel@tonic-gate 	if ((ioctl(fd, DKIOCGMBOOT, bootsect) < 0) && (errno != ENOTTY)) {
328*2174cb7bSVirginia Wray 		return (0);
3297c478bd9Sstevel@tonic-gate 	}
3307c478bd9Sstevel@tonic-gate 
3317c478bd9Sstevel@tonic-gate 	return (1);
3327c478bd9Sstevel@tonic-gate }
3337c478bd9Sstevel@tonic-gate 
3347c478bd9Sstevel@tonic-gate /*
335*2174cb7bSVirginia Wray  * partition_make_descriptors
336*2174cb7bSVirginia Wray  *
3377c478bd9Sstevel@tonic-gate  * A partition descriptor points to a disk, the name is the partition number
338*2174cb7bSVirginia Wray  * and the secondary name is the media name. The iparts parameter returned
339*2174cb7bSVirginia Wray  * by the get_parts function contains the structures of all of the identified
340*2174cb7bSVirginia Wray  * partitions found on each disk on a system. These are processed into an array
341*2174cb7bSVirginia Wray  * of descriptors. A descriptor contains all of the information about a
342*2174cb7bSVirginia Wray  * specific partition.
343*2174cb7bSVirginia Wray  *
344*2174cb7bSVirginia Wray  * Parameters:  none
345*2174cb7bSVirginia Wray  *
346*2174cb7bSVirginia Wray  * Returns:     0 on success
347*2174cb7bSVirginia Wray  *              Error value on failure
348*2174cb7bSVirginia Wray  *
3497c478bd9Sstevel@tonic-gate  */
350*2174cb7bSVirginia Wray 
3517c478bd9Sstevel@tonic-gate int
3527c478bd9Sstevel@tonic-gate partition_make_descriptors()
3537c478bd9Sstevel@tonic-gate {
3547c478bd9Sstevel@tonic-gate 	int		error;
3557c478bd9Sstevel@tonic-gate 	disk_t		*dp;
3567c478bd9Sstevel@tonic-gate 
3577c478bd9Sstevel@tonic-gate 	dp = cache_get_disklist();
3587c478bd9Sstevel@tonic-gate 	while (dp != NULL) {
359*2174cb7bSVirginia Wray 		struct ipart	iparts[TOTAL_NUMPART];
360*2174cb7bSVirginia Wray 		char		pname[MAXPATHLEN];
3617c478bd9Sstevel@tonic-gate 
362*2174cb7bSVirginia Wray 		if (get_parts(dp, iparts, pname, sizeof (pname)) == 0) {
363*2174cb7bSVirginia Wray 			int	i;
364*2174cb7bSVirginia Wray 			char	mname[MAXPATHLEN];
365*2174cb7bSVirginia Wray 			int	conv_flag = 0;
3663e1bd7a2Ssjelinek #if defined(i386) || defined(__amd64)
367*2174cb7bSVirginia Wray 			/* convert part. name (e.g. c0d0p1) */
368*2174cb7bSVirginia Wray 			int	len;
3697c478bd9Sstevel@tonic-gate 
370*2174cb7bSVirginia Wray 			len = strlen(pname);
371*2174cb7bSVirginia Wray 			if (len > 1 && *(pname + (len - 2)) == 'p') {
372*2174cb7bSVirginia Wray 				conv_flag = 1;
373*2174cb7bSVirginia Wray 				*(pname + (len - 1)) = 0;
3747c478bd9Sstevel@tonic-gate 			}
375*2174cb7bSVirginia Wray #endif
3767c478bd9Sstevel@tonic-gate 
377*2174cb7bSVirginia Wray 			mname[0] = 0;
378*2174cb7bSVirginia Wray 			(void) media_read_name(dp, mname, sizeof (mname));
379*2174cb7bSVirginia Wray 
380*2174cb7bSVirginia Wray 			/*
381*2174cb7bSVirginia Wray 			 * Process the descriptors and modify the cxdxpx
382*2174cb7bSVirginia Wray 			 * format so that it refers to the fdisk partition
383*2174cb7bSVirginia Wray 			 * number and not to the physical disk. This is
384*2174cb7bSVirginia Wray 			 * achieved by i+1, where i is the number of the
385*2174cb7bSVirginia Wray 			 * physical disk partition.
386*2174cb7bSVirginia Wray 			 */
387*2174cb7bSVirginia Wray 			for (i = 0; i < TOTAL_NUMPART; i++) {
388*2174cb7bSVirginia Wray 				if (iparts[i].systid != UNUSED) {
389*2174cb7bSVirginia Wray 					char    part_name[MAXPATHLEN];
390*2174cb7bSVirginia Wray 
391*2174cb7bSVirginia Wray 					if (conv_flag) {
392*2174cb7bSVirginia Wray 						/*
393*2174cb7bSVirginia Wray 						 * convert partition name
394*2174cb7bSVirginia Wray 						 * (e.g. c0d0p1)
395*2174cb7bSVirginia Wray 						 */
396*2174cb7bSVirginia Wray 						(void) snprintf(part_name,
397*2174cb7bSVirginia Wray 						    sizeof (part_name),
398*2174cb7bSVirginia Wray 						    "%s%d", pname, i+1);
399*2174cb7bSVirginia Wray 					} else {
400*2174cb7bSVirginia Wray 						(void) snprintf(part_name,
401*2174cb7bSVirginia Wray 						    sizeof (part_name),
402*2174cb7bSVirginia Wray 						    "%d", i+1);
403*2174cb7bSVirginia Wray 					}
404*2174cb7bSVirginia Wray 
405*2174cb7bSVirginia Wray 					cache_load_desc(DM_PARTITION, dp,
406*2174cb7bSVirginia Wray 					    part_name, mname, &error);
407*2174cb7bSVirginia Wray 					if (error != 0) {
408*2174cb7bSVirginia Wray 						return (error);
409*2174cb7bSVirginia Wray 					}
410*2174cb7bSVirginia Wray 				}
4117c478bd9Sstevel@tonic-gate 			}
4127c478bd9Sstevel@tonic-gate 		}
413*2174cb7bSVirginia Wray 		dp = dp->next;
4147c478bd9Sstevel@tonic-gate 	}
4157c478bd9Sstevel@tonic-gate 
4167c478bd9Sstevel@tonic-gate 	return (0);
4177c478bd9Sstevel@tonic-gate }
4187c478bd9Sstevel@tonic-gate 
4197c478bd9Sstevel@tonic-gate static int
4207c478bd9Sstevel@tonic-gate get_attrs(descriptor_t *dp, struct ipart *iparts, nvlist_t *attrs)
4217c478bd9Sstevel@tonic-gate {
4227c478bd9Sstevel@tonic-gate 	char		*p;
4237c478bd9Sstevel@tonic-gate 	int		part_num;
4247c478bd9Sstevel@tonic-gate 
4257c478bd9Sstevel@tonic-gate 	/*
4267c478bd9Sstevel@tonic-gate 	 * We already made sure the media was loaded and ready in the
4277c478bd9Sstevel@tonic-gate 	 * get_parts call within partition_get_attributes.
4287c478bd9Sstevel@tonic-gate 	 */
4297c478bd9Sstevel@tonic-gate 
4307c478bd9Sstevel@tonic-gate 	p = strrchr(dp->name, 'p');
4317c478bd9Sstevel@tonic-gate 	if (p == NULL) {
432*2174cb7bSVirginia Wray 		p = dp->name;
4337c478bd9Sstevel@tonic-gate 	} else {
434*2174cb7bSVirginia Wray 		p++;
4357c478bd9Sstevel@tonic-gate 	}
4367c478bd9Sstevel@tonic-gate 	part_num = atoi(p);
437*2174cb7bSVirginia Wray 	if (part_num > TOTAL_NUMPART ||
438*2174cb7bSVirginia Wray 	    iparts[part_num - 1].systid == UNUSED) {
439*2174cb7bSVirginia Wray 		return (ENODEV);
4407c478bd9Sstevel@tonic-gate 	}
4417c478bd9Sstevel@tonic-gate 
442*2174cb7bSVirginia Wray 	/*
443*2174cb7bSVirginia Wray 	 * A partition has been found. Determine what type of
444*2174cb7bSVirginia Wray 	 * partition it is: logical, extended, or primary.
445*2174cb7bSVirginia Wray 	 * Collect the information for the partition.
446*2174cb7bSVirginia Wray 	 */
447*2174cb7bSVirginia Wray #if defined(i386) || defined(__amd64)
448*2174cb7bSVirginia Wray 	if (part_num > FD_NUMPART) {
449*2174cb7bSVirginia Wray 		if (nvlist_add_uint32(attrs, DM_PARTITION_TYPE,
450*2174cb7bSVirginia Wray 		    DM_LOGICAL) != 0)  {
451*2174cb7bSVirginia Wray 			return (ENOMEM);
452*2174cb7bSVirginia Wray 		}
453*2174cb7bSVirginia Wray 	} else if (fdisk_is_dos_extended(iparts[part_num - 1].systid)) {
454*2174cb7bSVirginia Wray 		if (nvlist_add_uint32(attrs, DM_PARTITION_TYPE,
455*2174cb7bSVirginia Wray 		    DM_EXTENDED) != 0)  {
456*2174cb7bSVirginia Wray 			return (ENOMEM);
457*2174cb7bSVirginia Wray 		}
458*2174cb7bSVirginia Wray 
459*2174cb7bSVirginia Wray 	} else {
460*2174cb7bSVirginia Wray 		if (nvlist_add_uint32(attrs, DM_PARTITION_TYPE,
461*2174cb7bSVirginia Wray 		    DM_PRIMARY) != 0) {
462*2174cb7bSVirginia Wray 			return (ENOMEM);
463*2174cb7bSVirginia Wray 		}
464*2174cb7bSVirginia Wray 	}
465*2174cb7bSVirginia Wray #endif
466*2174cb7bSVirginia Wray 
467*2174cb7bSVirginia Wray #ifdef sparc
468*2174cb7bSVirginia Wray 	if (nvlist_add_uint32(attrs, DM_PARTITION_TYPE,
469*2174cb7bSVirginia Wray 	    DM_PRIMARY) != 0) {
470*2174cb7bSVirginia Wray 		return (ENOMEM);
471*2174cb7bSVirginia Wray 	}
472*2174cb7bSVirginia Wray #endif
473*2174cb7bSVirginia Wray 
4747c478bd9Sstevel@tonic-gate 
4757c478bd9Sstevel@tonic-gate 	if (nvlist_add_uint32(attrs, DM_BOOTID,
476*2174cb7bSVirginia Wray 	    (unsigned int)iparts[part_num - 1].bootid) != 0) {
477*2174cb7bSVirginia Wray 		return (ENOMEM);
4787c478bd9Sstevel@tonic-gate 	}
4797c478bd9Sstevel@tonic-gate 
4807c478bd9Sstevel@tonic-gate 	if (nvlist_add_uint32(attrs, DM_PTYPE,
481*2174cb7bSVirginia Wray 	    (unsigned int)iparts[part_num - 1].systid) != 0) {
482*2174cb7bSVirginia Wray 		return (ENOMEM);
4837c478bd9Sstevel@tonic-gate 	}
4847c478bd9Sstevel@tonic-gate 
4857c478bd9Sstevel@tonic-gate 	if (nvlist_add_uint32(attrs, DM_BHEAD,
486*2174cb7bSVirginia Wray 	    (unsigned int)iparts[part_num - 1].beghead) != 0) {
487*2174cb7bSVirginia Wray 		return (ENOMEM);
4887c478bd9Sstevel@tonic-gate 	}
4897c478bd9Sstevel@tonic-gate 
4907c478bd9Sstevel@tonic-gate 	if (nvlist_add_uint32(attrs, DM_BSECT,
491*2174cb7bSVirginia Wray 	    (unsigned int)((iparts[part_num - 1].begsect) & 0x3f)) != 0) {
492*2174cb7bSVirginia Wray 		return (ENOMEM);
4937c478bd9Sstevel@tonic-gate 	}
4947c478bd9Sstevel@tonic-gate 
4957c478bd9Sstevel@tonic-gate 	if (nvlist_add_uint32(attrs, DM_BCYL, (unsigned int)
496*2174cb7bSVirginia Wray 	    ((iparts[part_num - 1].begcyl & 0xff) |
497*2174cb7bSVirginia Wray 	    ((iparts[part_num - 1].begsect & 0xc0) << 2))) != 0) {
498*2174cb7bSVirginia Wray 		return (ENOMEM);
4997c478bd9Sstevel@tonic-gate 	}
5007c478bd9Sstevel@tonic-gate 
5017c478bd9Sstevel@tonic-gate 	if (nvlist_add_uint32(attrs, DM_EHEAD,
502*2174cb7bSVirginia Wray 	    (unsigned int)iparts[part_num - 1].endhead) != 0) {
503*2174cb7bSVirginia Wray 		return (ENOMEM);
5047c478bd9Sstevel@tonic-gate 	}
5057c478bd9Sstevel@tonic-gate 
5067c478bd9Sstevel@tonic-gate 	if (nvlist_add_uint32(attrs, DM_ESECT,
507*2174cb7bSVirginia Wray 	    (unsigned int)((iparts[part_num - 1].endsect) & 0x3f)) != 0) {
508*2174cb7bSVirginia Wray 		return (ENOMEM);
5097c478bd9Sstevel@tonic-gate 	}
5107c478bd9Sstevel@tonic-gate 
5117c478bd9Sstevel@tonic-gate 	if (nvlist_add_uint32(attrs, DM_ECYL, (unsigned int)
512*2174cb7bSVirginia Wray 	    ((iparts[part_num - 1].endcyl & 0xff) |
513*2174cb7bSVirginia Wray 	    ((iparts[part_num - 1].endsect & 0xc0) << 2))) != 0) {
514*2174cb7bSVirginia Wray 		return (ENOMEM);
5157c478bd9Sstevel@tonic-gate 	}
5167c478bd9Sstevel@tonic-gate 
5177c478bd9Sstevel@tonic-gate 	if (nvlist_add_uint32(attrs, DM_RELSECT,
518*2174cb7bSVirginia Wray 	    (unsigned int)iparts[part_num - 1].relsect) != 0) {
519*2174cb7bSVirginia Wray 		return (ENOMEM);
5207c478bd9Sstevel@tonic-gate 	}
5217c478bd9Sstevel@tonic-gate 
5227c478bd9Sstevel@tonic-gate 	if (nvlist_add_uint32(attrs, DM_NSECTORS,
523*2174cb7bSVirginia Wray 	    (unsigned int)iparts[part_num - 1].numsect) != 0) {
524*2174cb7bSVirginia Wray 		return (ENOMEM);
5257c478bd9Sstevel@tonic-gate 	}
5267c478bd9Sstevel@tonic-gate 
5277c478bd9Sstevel@tonic-gate 	return (0);
5287c478bd9Sstevel@tonic-gate }
5297c478bd9Sstevel@tonic-gate 
530*2174cb7bSVirginia Wray /*
531*2174cb7bSVirginia Wray  * get_parts
532*2174cb7bSVirginia Wray  * Discovers the primary, extended, and logical partitions that have
533*2174cb7bSVirginia Wray  * been created on a disk. get_parts loops through the partitions,
534*2174cb7bSVirginia Wray  * collects the information on each partition and stores it in a
535*2174cb7bSVirginia Wray  * partition table.
536*2174cb7bSVirginia Wray  *
537*2174cb7bSVirginia Wray  * Parameters;
538*2174cb7bSVirginia Wray  *		disk		-The disk device to be evaluated for partitions
539*2174cb7bSVirginia Wray  *		iparts		-The structure that holds information about
540*2174cb7bSVirginia Wray  *				 the partitions
541*2174cb7bSVirginia Wray  *		opath		-The device path
542*2174cb7bSVirginia Wray  *		opath_len 	-Buffer size used with opath
543*2174cb7bSVirginia Wray  * Returns:
544*2174cb7bSVirginia Wray  *		0 on Successful completion
545*2174cb7bSVirginia Wray  *		Error Value on failure
546*2174cb7bSVirginia Wray  *
547*2174cb7bSVirginia Wray  */
5487c478bd9Sstevel@tonic-gate static int
5497c478bd9Sstevel@tonic-gate get_parts(disk_t *disk, struct ipart *iparts, char *opath, int opath_len)
5507c478bd9Sstevel@tonic-gate {
5517c478bd9Sstevel@tonic-gate 	int		fd;
5527c478bd9Sstevel@tonic-gate 	struct dk_minfo	minfo;
5537c478bd9Sstevel@tonic-gate 	struct mboot	bootblk;
5547c478bd9Sstevel@tonic-gate 	char		bootsect[512];
5557c478bd9Sstevel@tonic-gate 	int		i;
5567c478bd9Sstevel@tonic-gate 
557*2174cb7bSVirginia Wray #if defined(i386) || defined(__amd64)
558*2174cb7bSVirginia Wray 	int 		j, ret;
559*2174cb7bSVirginia Wray 	ext_part_t	*epp;		/* extended partition structure */
560*2174cb7bSVirginia Wray 	char 		*device;	/* name of fixed disk drive */
561*2174cb7bSVirginia Wray 	size_t 		len;
562*2174cb7bSVirginia Wray 	logical_drive_t	*log_drv;	/* logical drive structure */
563*2174cb7bSVirginia Wray 	uint64_t 	tmpsect;
564*2174cb7bSVirginia Wray #endif
565*2174cb7bSVirginia Wray 
5667c478bd9Sstevel@tonic-gate 	/* Can't use drive_open_disk since we need the partition dev name. */
5677c478bd9Sstevel@tonic-gate 	if ((fd = open_disk(disk, opath, opath_len)) < 0) {
568*2174cb7bSVirginia Wray 		return (ENODEV);
5697c478bd9Sstevel@tonic-gate 	}
5707c478bd9Sstevel@tonic-gate 
5717c478bd9Sstevel@tonic-gate 	/* First make sure media is inserted and spun up. */
5727c478bd9Sstevel@tonic-gate 	if (!media_read_info(fd, &minfo)) {
573*2174cb7bSVirginia Wray 		(void) close(fd);
574*2174cb7bSVirginia Wray 		return (ENODEV);
5757c478bd9Sstevel@tonic-gate 	}
5767c478bd9Sstevel@tonic-gate 
5777c478bd9Sstevel@tonic-gate 	if (!partition_has_fdisk(disk, fd)) {
578*2174cb7bSVirginia Wray 		(void) close(fd);
579*2174cb7bSVirginia Wray 		return (ENOTTY);
5807c478bd9Sstevel@tonic-gate 	}
5817c478bd9Sstevel@tonic-gate 
5827c478bd9Sstevel@tonic-gate 	if (lseek(fd, 0, 0) == -1) {
583*2174cb7bSVirginia Wray 		(void) close(fd);
584*2174cb7bSVirginia Wray 		return (ENODEV);
5857c478bd9Sstevel@tonic-gate 	}
5867c478bd9Sstevel@tonic-gate 
5877c478bd9Sstevel@tonic-gate 	if (read(fd, bootsect, 512) != 512) {
588*2174cb7bSVirginia Wray 		(void) close(fd);
589*2174cb7bSVirginia Wray 		return (ENODEV);
5907c478bd9Sstevel@tonic-gate 	}
5917c478bd9Sstevel@tonic-gate 	(void) close(fd);
5927c478bd9Sstevel@tonic-gate 
5937c478bd9Sstevel@tonic-gate 	(void) memcpy(&bootblk, bootsect, sizeof (bootblk));
5947c478bd9Sstevel@tonic-gate 
5957c478bd9Sstevel@tonic-gate 	if (les(bootblk.signature) != MBB_MAGIC)  {
596*2174cb7bSVirginia Wray 		return (ENOTTY);
597*2174cb7bSVirginia Wray 	}
598*2174cb7bSVirginia Wray 
599*2174cb7bSVirginia Wray 	/*
600*2174cb7bSVirginia Wray 	 * Initialize the memory space to clear unknown garbage
601*2174cb7bSVirginia Wray 	 * that might create confusing results.
602*2174cb7bSVirginia Wray 	 */
603*2174cb7bSVirginia Wray 	for (i = 0;  i < TOTAL_NUMPART; i++) {
604*2174cb7bSVirginia Wray 		memset(&iparts[i], 0, sizeof (struct ipart));
605*2174cb7bSVirginia Wray 		iparts[i].systid = UNUSED;
6067c478bd9Sstevel@tonic-gate 	}
6077c478bd9Sstevel@tonic-gate 
6087c478bd9Sstevel@tonic-gate 	(void) memcpy(iparts, bootblk.parts, ISIZE);
6097c478bd9Sstevel@tonic-gate 
610*2174cb7bSVirginia Wray 	/*
611*2174cb7bSVirginia Wray 	 * Check to see if a valid partition exists. If a valid partition
612*2174cb7bSVirginia Wray 	 * exists, check to see if it is an extended partition.
613*2174cb7bSVirginia Wray 	 * If an extended partition exists, collect the logical partition
614*2174cb7bSVirginia Wray 	 * data.
615*2174cb7bSVirginia Wray 	 */
6167c478bd9Sstevel@tonic-gate 	for (i = 0; i < FD_NUMPART; i++) {
617*2174cb7bSVirginia Wray 		if (iparts[i].systid == UNUSED)
618*2174cb7bSVirginia Wray 			continue;
619*2174cb7bSVirginia Wray 
6207c478bd9Sstevel@tonic-gate 		iparts[i].relsect = lel(iparts[i].relsect);
6217c478bd9Sstevel@tonic-gate 		iparts[i].numsect = lel(iparts[i].numsect);
622*2174cb7bSVirginia Wray 
623*2174cb7bSVirginia Wray #if defined(i386) || defined(__amd64)
624*2174cb7bSVirginia Wray 		if (!fdisk_is_dos_extended(iparts[i].systid))
625*2174cb7bSVirginia Wray 			continue;
626*2174cb7bSVirginia Wray 
627*2174cb7bSVirginia Wray 		len = strlen(disk->aliases->alias) + strlen("/dev/rdsk/") + 1;
628*2174cb7bSVirginia Wray 		if ((device = malloc(len)) == NULL) {
629*2174cb7bSVirginia Wray 			if (device)
630*2174cb7bSVirginia Wray 				free(device);
631*2174cb7bSVirginia Wray 			continue;
632*2174cb7bSVirginia Wray 		}
633*2174cb7bSVirginia Wray 
634*2174cb7bSVirginia Wray 		/* Check the above fix w Jean */
635*2174cb7bSVirginia Wray 		(void) snprintf(device, len, "/dev/rdsk/%s",
636*2174cb7bSVirginia Wray 		    disk->aliases->alias);
637*2174cb7bSVirginia Wray 
638*2174cb7bSVirginia Wray 		if ((ret = libfdisk_init(&epp, device, &iparts[i],
639*2174cb7bSVirginia Wray 		    FDISK_READ_DISK)) != FDISK_SUCCESS) {
640*2174cb7bSVirginia Wray 
641*2174cb7bSVirginia Wray 			switch (ret) {
642*2174cb7bSVirginia Wray 				/*
643*2174cb7bSVirginia Wray 				 * The first 2 error cases indicate that
644*2174cb7bSVirginia Wray 				 * there is no Solaris logical partition,
645*2174cb7bSVirginia Wray 				 * which is a valid condition,
646*2174cb7bSVirginia Wray 				 * so iterating through the disk continues.
647*2174cb7bSVirginia Wray 				 * Any other error cases indicate there is
648*2174cb7bSVirginia Wray 				 * a potential problem with the disk, so
649*2174cb7bSVirginia Wray 				 * don't continue iterating through the disk
650*2174cb7bSVirginia Wray 				 * and return an error.
651*2174cb7bSVirginia Wray 				 */
652*2174cb7bSVirginia Wray 				case FDISK_EBADLOGDRIVE:
653*2174cb7bSVirginia Wray 				case FDISK_ENOLOGDRIVE:
654*2174cb7bSVirginia Wray 					free(device);
655*2174cb7bSVirginia Wray 					continue;
656*2174cb7bSVirginia Wray 				default:
657*2174cb7bSVirginia Wray 					free(device);
658*2174cb7bSVirginia Wray 					return (ENODEV);
659*2174cb7bSVirginia Wray 			}
660*2174cb7bSVirginia Wray 		}
661*2174cb7bSVirginia Wray 
662*2174cb7bSVirginia Wray 		/*
663*2174cb7bSVirginia Wray 		 * Collect logical drive information
664*2174cb7bSVirginia Wray 		 */
665*2174cb7bSVirginia Wray 		for (log_drv = fdisk_get_ld_head(epp),  j = FD_NUMPART,
666*2174cb7bSVirginia Wray 		    tmpsect = 0; (j < TOTAL_NUMPART) && (log_drv != NULL);
667*2174cb7bSVirginia Wray 		    log_drv = log_drv->next, j++) {
668*2174cb7bSVirginia Wray 			iparts[j].bootid = log_drv->parts[0].bootid;
669*2174cb7bSVirginia Wray 			iparts[j].beghead = log_drv->parts[0].beghead;
670*2174cb7bSVirginia Wray 			iparts[j].begsect = log_drv->parts[0].begsect;
671*2174cb7bSVirginia Wray 			iparts[j].begcyl = log_drv->parts[0].begcyl;
672*2174cb7bSVirginia Wray 			iparts[j].systid = log_drv->parts[0].systid;
673*2174cb7bSVirginia Wray 			iparts[j].endhead = log_drv->parts[0].endhead;
674*2174cb7bSVirginia Wray 			iparts[j].endsect = log_drv->parts[0].endsect;
675*2174cb7bSVirginia Wray 			iparts[j].endcyl = log_drv->parts[0].endcyl;
676*2174cb7bSVirginia Wray 			iparts[j].relsect = (tmpsect +
677*2174cb7bSVirginia Wray 			    lel(log_drv->parts[0].relsect) + epp->ext_beg_sec);
678*2174cb7bSVirginia Wray 			iparts[j].numsect = lel(log_drv->parts[0].numsect);
679*2174cb7bSVirginia Wray 			tmpsect = lel(log_drv->parts[1].relsect);
680*2174cb7bSVirginia Wray 		}
681*2174cb7bSVirginia Wray 
682*2174cb7bSVirginia Wray 		/* free the device and the epp memory. */
683*2174cb7bSVirginia Wray 		free(device);
684*2174cb7bSVirginia Wray 		libfdisk_fini(&epp);
685*2174cb7bSVirginia Wray #endif
6867c478bd9Sstevel@tonic-gate 	}
6877c478bd9Sstevel@tonic-gate 
6887c478bd9Sstevel@tonic-gate 	return (0);
6897c478bd9Sstevel@tonic-gate }
690*2174cb7bSVirginia Wray 
6917c478bd9Sstevel@tonic-gate /* return 1 if the partition descriptor is still valid, 0 if not. */
6927c478bd9Sstevel@tonic-gate static int
6937c478bd9Sstevel@tonic-gate desc_ok(descriptor_t *dp)
6947c478bd9Sstevel@tonic-gate {
6957c478bd9Sstevel@tonic-gate 	/* First verify the media name for removable media */
6967c478bd9Sstevel@tonic-gate 	if (dp->p.disk->removable) {
697*2174cb7bSVirginia Wray 		char	mname[MAXPATHLEN];
6987c478bd9Sstevel@tonic-gate 
699*2174cb7bSVirginia Wray 		if (!media_read_name(dp->p.disk, mname, sizeof (mname))) {
700*2174cb7bSVirginia Wray 			return (0);
701*2174cb7bSVirginia Wray 		}
7027c478bd9Sstevel@tonic-gate 
703*2174cb7bSVirginia Wray 		if (mname[0] == 0) {
704*2174cb7bSVirginia Wray 			return (libdiskmgt_str_eq(dp->secondary_name, NULL));
705*2174cb7bSVirginia Wray 		} else {
706*2174cb7bSVirginia Wray 			return (libdiskmgt_str_eq(dp->secondary_name, mname));
707*2174cb7bSVirginia Wray 		}
7087c478bd9Sstevel@tonic-gate 	}
7097c478bd9Sstevel@tonic-gate 
7107c478bd9Sstevel@tonic-gate 	/*
7117c478bd9Sstevel@tonic-gate 	 * We could verify the partition is still there but this is kind of
7127c478bd9Sstevel@tonic-gate 	 * expensive and other code down the line will do that (e.g. see
7137c478bd9Sstevel@tonic-gate 	 * get_attrs).
7147c478bd9Sstevel@tonic-gate 	 */
7157c478bd9Sstevel@tonic-gate 
7167c478bd9Sstevel@tonic-gate 	return (1);
7177c478bd9Sstevel@tonic-gate }
7187c478bd9Sstevel@tonic-gate 
7197c478bd9Sstevel@tonic-gate /*
7207c478bd9Sstevel@tonic-gate  * Return 1 if partition has slices, 0 if not.
7217c478bd9Sstevel@tonic-gate  */
7227c478bd9Sstevel@tonic-gate static int
7237c478bd9Sstevel@tonic-gate has_slices(descriptor_t *desc, int *errp)
7247c478bd9Sstevel@tonic-gate {
7257c478bd9Sstevel@tonic-gate 	int		pnum;
7267c478bd9Sstevel@tonic-gate 	int		i;
7277c478bd9Sstevel@tonic-gate 	char		*p;
728*2174cb7bSVirginia Wray 	struct ipart	iparts[TOTAL_NUMPART];
7297c478bd9Sstevel@tonic-gate 
7307c478bd9Sstevel@tonic-gate 	if (get_parts(desc->p.disk, iparts, NULL, 0) != 0) {
731*2174cb7bSVirginia Wray 		*errp = ENODEV;
732*2174cb7bSVirginia Wray 		return (0);
7337c478bd9Sstevel@tonic-gate 	}
7347c478bd9Sstevel@tonic-gate 
7357c478bd9Sstevel@tonic-gate 	p = strrchr(desc->name, 'p');
7367c478bd9Sstevel@tonic-gate 	if (p == NULL) {
737*2174cb7bSVirginia Wray 		p = desc->name;
7387c478bd9Sstevel@tonic-gate 	} else {
739*2174cb7bSVirginia Wray 		p++;
7407c478bd9Sstevel@tonic-gate 	}
7417c478bd9Sstevel@tonic-gate 	pnum = atoi(p);
7427c478bd9Sstevel@tonic-gate 
7437c478bd9Sstevel@tonic-gate 	/*
7447c478bd9Sstevel@tonic-gate 	 * Slices are associated with the active solaris partition or if there
7457c478bd9Sstevel@tonic-gate 	 * is no active solaris partition, then the first solaris partition.
7467c478bd9Sstevel@tonic-gate 	 */
7477c478bd9Sstevel@tonic-gate 
7487c478bd9Sstevel@tonic-gate 	*errp = 0;
7497c478bd9Sstevel@tonic-gate 	if (iparts[pnum].bootid == ACTIVE &&
7507c478bd9Sstevel@tonic-gate 	    (iparts[pnum].systid == SUNIXOS ||
7517c478bd9Sstevel@tonic-gate 	    iparts[pnum].systid == SUNIXOS2)) {
7527c478bd9Sstevel@tonic-gate 		return (1);
7537c478bd9Sstevel@tonic-gate 	} else {
754*2174cb7bSVirginia Wray 		int	active = 0;
755*2174cb7bSVirginia Wray 
756*2174cb7bSVirginia Wray 		/* Check if there are no active solaris partitions. */
757*2174cb7bSVirginia Wray 		for (i = 0; i < TOTAL_NUMPART; i++) {
758*2174cb7bSVirginia Wray 			if (iparts[i].bootid == ACTIVE &&
759*2174cb7bSVirginia Wray 			    (iparts[i].systid == SUNIXOS ||
760*2174cb7bSVirginia Wray 			    iparts[i].systid == SUNIXOS2)) {
761*2174cb7bSVirginia Wray 				active = 1;
762*2174cb7bSVirginia Wray 				break;
763*2174cb7bSVirginia Wray 			}
7647c478bd9Sstevel@tonic-gate 		}
7657c478bd9Sstevel@tonic-gate 
766*2174cb7bSVirginia Wray 		if (!active) {
767*2174cb7bSVirginia Wray 			/* Check if this is the first solaris partition. */
768*2174cb7bSVirginia Wray 			for (i = 0; i < TOTAL_NUMPART; i++) {
769*2174cb7bSVirginia Wray 				if (iparts[i].systid == SUNIXOS ||
770*2174cb7bSVirginia Wray 				    iparts[i].systid == SUNIXOS2) {
771*2174cb7bSVirginia Wray 					break;
772*2174cb7bSVirginia Wray 				}
773*2174cb7bSVirginia Wray 			}
774*2174cb7bSVirginia Wray 
775*2174cb7bSVirginia Wray 			if (i < TOTAL_NUMPART && i == pnum) {
776*2174cb7bSVirginia Wray 				return (1);
777*2174cb7bSVirginia Wray 			}
7787c478bd9Sstevel@tonic-gate 		}
7797c478bd9Sstevel@tonic-gate 	}
7807c478bd9Sstevel@tonic-gate 
7817c478bd9Sstevel@tonic-gate 	return (0);
7827c478bd9Sstevel@tonic-gate }
7837c478bd9Sstevel@tonic-gate 
7847c478bd9Sstevel@tonic-gate static int
7857c478bd9Sstevel@tonic-gate open_disk(disk_t *diskp, char *opath, int len)
7867c478bd9Sstevel@tonic-gate {
7877c478bd9Sstevel@tonic-gate 	/*
78818c2aff7Sartem 	 * Just open the first devpath.
7897c478bd9Sstevel@tonic-gate 	 */
7907c478bd9Sstevel@tonic-gate 	if (diskp->aliases != NULL && diskp->aliases->devpaths != NULL) {
7917c478bd9Sstevel@tonic-gate #ifdef sparc
792*2174cb7bSVirginia Wray 	if (opath != NULL) {
7937c478bd9Sstevel@tonic-gate 		(void) strlcpy(opath, diskp->aliases->devpaths->devpath, len);
794*2174cb7bSVirginia Wray 	}
795*2174cb7bSVirginia Wray 	return (open(diskp->aliases->devpaths->devpath, O_RDONLY|O_NDELAY));
7967c478bd9Sstevel@tonic-gate #else
797*2174cb7bSVirginia Wray 	/* On intel we need to open partition device (e.g. c0d0p1). */
798*2174cb7bSVirginia Wray 	char	part_dev[MAXPATHLEN];
799*2174cb7bSVirginia Wray 	char	*p;
800*2174cb7bSVirginia Wray 
801*2174cb7bSVirginia Wray 	(void) strlcpy(part_dev, diskp->aliases->devpaths->devpath,
802*2174cb7bSVirginia Wray 	    sizeof (part_dev));
803*2174cb7bSVirginia Wray 	p = strrchr(part_dev, '/');
804*2174cb7bSVirginia Wray 	if (p == NULL) {
8057c478bd9Sstevel@tonic-gate 		p = strrchr(part_dev, 's');
8067c478bd9Sstevel@tonic-gate 		if (p != NULL) {
807*2174cb7bSVirginia Wray 			*p = 'p';
8087c478bd9Sstevel@tonic-gate 		}
809*2174cb7bSVirginia Wray 	} else {
8107c478bd9Sstevel@tonic-gate 		char *ps;
8117c478bd9Sstevel@tonic-gate 
8127c478bd9Sstevel@tonic-gate 		*p = 0;
8137c478bd9Sstevel@tonic-gate 		ps = strrchr((p + 1), 's');
8147c478bd9Sstevel@tonic-gate 		if (ps != NULL) {
815*2174cb7bSVirginia Wray 			*ps = 'p';
8167c478bd9Sstevel@tonic-gate 		}
8177c478bd9Sstevel@tonic-gate 		*p = '/';
818*2174cb7bSVirginia Wray 	}
8197c478bd9Sstevel@tonic-gate 
820*2174cb7bSVirginia Wray 	if (opath != NULL) {
8217c478bd9Sstevel@tonic-gate 		(void) strlcpy(opath, part_dev, len);
822*2174cb7bSVirginia Wray 	}
823*2174cb7bSVirginia Wray 	return (open(part_dev, O_RDONLY|O_NDELAY));
8247c478bd9Sstevel@tonic-gate #endif
8257c478bd9Sstevel@tonic-gate 	}
8267c478bd9Sstevel@tonic-gate 
8277c478bd9Sstevel@tonic-gate 	return (-1);
8287c478bd9Sstevel@tonic-gate }
829