10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*2912Sartem * Common Development and Distribution License (the "License"). 6*2912Sartem * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 210Sstevel@tonic-gate /* 22*2912Sartem * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 230Sstevel@tonic-gate * Use is subject to license terms. 240Sstevel@tonic-gate */ 250Sstevel@tonic-gate 260Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 270Sstevel@tonic-gate 280Sstevel@tonic-gate #include <fcntl.h> 290Sstevel@tonic-gate #include <libdevinfo.h> 300Sstevel@tonic-gate #include <stdio.h> 310Sstevel@tonic-gate #include <stdlib.h> 320Sstevel@tonic-gate #include <string.h> 330Sstevel@tonic-gate #include <sys/sunddi.h> 340Sstevel@tonic-gate #include <sys/types.h> 350Sstevel@tonic-gate #include <sys/stat.h> 360Sstevel@tonic-gate #include <dirent.h> 370Sstevel@tonic-gate #include <unistd.h> 380Sstevel@tonic-gate #include <sys/dkio.h> 390Sstevel@tonic-gate 400Sstevel@tonic-gate #include "libdiskmgt.h" 410Sstevel@tonic-gate #include "disks_private.h" 420Sstevel@tonic-gate #include "partition.h" 430Sstevel@tonic-gate 440Sstevel@tonic-gate #ifdef sparc 450Sstevel@tonic-gate #define les(val) ((((val)&0xFF)<<8)|(((val)>>8)&0xFF)) 460Sstevel@tonic-gate #define lel(val) (((unsigned)(les((val)&0x0000FFFF))<<16) | \ 470Sstevel@tonic-gate (les((unsigned)((val)&0xffff0000)>>16))) 480Sstevel@tonic-gate #else 490Sstevel@tonic-gate #define les(val) (val) 500Sstevel@tonic-gate #define lel(val) (val) 510Sstevel@tonic-gate #endif 520Sstevel@tonic-gate 530Sstevel@tonic-gate #define ISIZE FD_NUMPART * sizeof (struct ipart) 540Sstevel@tonic-gate 550Sstevel@tonic-gate static int desc_ok(descriptor_t *dp); 560Sstevel@tonic-gate static int get_attrs(descriptor_t *dp, struct ipart *iparts, 570Sstevel@tonic-gate nvlist_t *attrs); 580Sstevel@tonic-gate static int get_parts(disk_t *disk, struct ipart *iparts, char *opath, 590Sstevel@tonic-gate int opath_len); 600Sstevel@tonic-gate static int open_disk(disk_t *diskp, char *opath, int len); 610Sstevel@tonic-gate static int has_slices(descriptor_t *desc, int *errp); 620Sstevel@tonic-gate 630Sstevel@tonic-gate descriptor_t ** 640Sstevel@tonic-gate partition_get_assoc_descriptors(descriptor_t *desc, dm_desc_type_t type, 650Sstevel@tonic-gate int *errp) 660Sstevel@tonic-gate { 670Sstevel@tonic-gate if (!desc_ok(desc)) { 680Sstevel@tonic-gate *errp = ENODEV; 690Sstevel@tonic-gate return (NULL); 700Sstevel@tonic-gate } 710Sstevel@tonic-gate 720Sstevel@tonic-gate switch (type) { 730Sstevel@tonic-gate case DM_MEDIA: 740Sstevel@tonic-gate return (media_get_assocs(desc, errp)); 750Sstevel@tonic-gate case DM_SLICE: 760Sstevel@tonic-gate if (!has_slices(desc, errp)) { 770Sstevel@tonic-gate if (*errp != 0) { 780Sstevel@tonic-gate return (NULL); 790Sstevel@tonic-gate } 800Sstevel@tonic-gate return (libdiskmgt_empty_desc_array(errp)); 810Sstevel@tonic-gate } 820Sstevel@tonic-gate return (slice_get_assocs(desc, errp)); 830Sstevel@tonic-gate } 840Sstevel@tonic-gate 850Sstevel@tonic-gate *errp = EINVAL; 860Sstevel@tonic-gate return (NULL); 870Sstevel@tonic-gate } 880Sstevel@tonic-gate 890Sstevel@tonic-gate /* 900Sstevel@tonic-gate * This is called by media/slice to get the associated partitions. 910Sstevel@tonic-gate * For a media desc. we just get all the partitions, but for a slice desc. 920Sstevel@tonic-gate * we just get the active solaris partition. 930Sstevel@tonic-gate */ 940Sstevel@tonic-gate descriptor_t ** 950Sstevel@tonic-gate partition_get_assocs(descriptor_t *desc, int *errp) 960Sstevel@tonic-gate { 970Sstevel@tonic-gate descriptor_t **partitions; 980Sstevel@tonic-gate int pos; 990Sstevel@tonic-gate int i; 1000Sstevel@tonic-gate struct ipart iparts[FD_NUMPART]; 1010Sstevel@tonic-gate char pname[MAXPATHLEN]; 1020Sstevel@tonic-gate int conv_flag = 0; 103767Ssjelinek #if defined(i386) || defined(__amd64) 104767Ssjelinek int len; 105767Ssjelinek #endif 1060Sstevel@tonic-gate 1070Sstevel@tonic-gate if (get_parts(desc->p.disk, iparts, pname, sizeof (pname)) != 0) { 1080Sstevel@tonic-gate return (libdiskmgt_empty_desc_array(errp)); 1090Sstevel@tonic-gate } 1100Sstevel@tonic-gate 1110Sstevel@tonic-gate /* allocate the array for the descriptors */ 1120Sstevel@tonic-gate partitions = (descriptor_t **)calloc(FD_NUMPART + 1, 1130Sstevel@tonic-gate sizeof (descriptor_t *)); 1140Sstevel@tonic-gate if (partitions == NULL) { 1150Sstevel@tonic-gate *errp = ENOMEM; 1160Sstevel@tonic-gate return (NULL); 1170Sstevel@tonic-gate } 1180Sstevel@tonic-gate 119767Ssjelinek #if defined(i386) || defined(__amd64) 1200Sstevel@tonic-gate /* convert part. name (e.g. c0d0p0) */ 1210Sstevel@tonic-gate len = strlen(pname); 1220Sstevel@tonic-gate if (len > 1 && *(pname + (len - 2)) == 'p') { 1230Sstevel@tonic-gate conv_flag = 1; 1240Sstevel@tonic-gate *(pname + (len - 1)) = 0; 1250Sstevel@tonic-gate } 1260Sstevel@tonic-gate #endif 1270Sstevel@tonic-gate 1280Sstevel@tonic-gate /* 1290Sstevel@tonic-gate * If this is a slice desc. we need the first active solaris partition 1300Sstevel@tonic-gate * and if there isn't one then we need the first solaris partition. 1310Sstevel@tonic-gate */ 1320Sstevel@tonic-gate if (desc->type == DM_SLICE) { 1330Sstevel@tonic-gate for (i = 0; i < FD_NUMPART; i++) { 1340Sstevel@tonic-gate if (iparts[i].bootid == ACTIVE && 1350Sstevel@tonic-gate (iparts[i].systid == SUNIXOS || 1360Sstevel@tonic-gate iparts[i].systid == SUNIXOS2)) { 1370Sstevel@tonic-gate break; 1380Sstevel@tonic-gate } 1390Sstevel@tonic-gate } 1400Sstevel@tonic-gate 1410Sstevel@tonic-gate /* no active solaris part., try to get the first solaris part. */ 1420Sstevel@tonic-gate if (i >= FD_NUMPART) { 1430Sstevel@tonic-gate for (i = 0; i < FD_NUMPART; i++) { 1440Sstevel@tonic-gate if (iparts[i].systid == SUNIXOS || 1450Sstevel@tonic-gate iparts[i].systid == SUNIXOS2) { 1460Sstevel@tonic-gate break; 1470Sstevel@tonic-gate } 1480Sstevel@tonic-gate } 1490Sstevel@tonic-gate } 1500Sstevel@tonic-gate 1510Sstevel@tonic-gate if (i < FD_NUMPART) { 1520Sstevel@tonic-gate /* we found a solaris partition to use */ 1530Sstevel@tonic-gate char part_name[MAXPATHLEN]; 1540Sstevel@tonic-gate 1550Sstevel@tonic-gate if (conv_flag) { 1560Sstevel@tonic-gate /* convert part. name (e.g. c0d0p0) */ 1570Sstevel@tonic-gate (void) snprintf(part_name, sizeof (part_name), "%s%d", 1580Sstevel@tonic-gate pname, i); 1590Sstevel@tonic-gate } else { 1600Sstevel@tonic-gate (void) snprintf(part_name, sizeof (part_name), "%d", i); 1610Sstevel@tonic-gate } 1620Sstevel@tonic-gate 1630Sstevel@tonic-gate /* the media name comes from the slice desc. */ 1640Sstevel@tonic-gate partitions[0] = cache_get_desc(DM_PARTITION, desc->p.disk, 1650Sstevel@tonic-gate part_name, desc->secondary_name, errp); 1660Sstevel@tonic-gate if (*errp != 0) { 1670Sstevel@tonic-gate cache_free_descriptors(partitions); 1680Sstevel@tonic-gate return (NULL); 1690Sstevel@tonic-gate } 1700Sstevel@tonic-gate partitions[1] = NULL; 1710Sstevel@tonic-gate 1720Sstevel@tonic-gate return (partitions); 1730Sstevel@tonic-gate 1740Sstevel@tonic-gate } 1750Sstevel@tonic-gate 1760Sstevel@tonic-gate return (libdiskmgt_empty_desc_array(errp)); 1770Sstevel@tonic-gate } 1780Sstevel@tonic-gate 1790Sstevel@tonic-gate /* Must be for media, so get all the parts. */ 1800Sstevel@tonic-gate 1810Sstevel@tonic-gate pos = 0; 1820Sstevel@tonic-gate for (i = 0; i < FD_NUMPART; i++) { 1830Sstevel@tonic-gate if (iparts[i].systid != 0) { 1840Sstevel@tonic-gate char part_name[MAXPATHLEN]; 1850Sstevel@tonic-gate 1860Sstevel@tonic-gate if (conv_flag) { 1870Sstevel@tonic-gate /* convert part. name (e.g. c0d0p0) */ 1880Sstevel@tonic-gate (void) snprintf(part_name, sizeof (part_name), "%s%d", 1890Sstevel@tonic-gate pname, i); 1900Sstevel@tonic-gate } else { 1910Sstevel@tonic-gate (void) snprintf(part_name, sizeof (part_name), "%d", i); 1920Sstevel@tonic-gate } 1930Sstevel@tonic-gate 1940Sstevel@tonic-gate /* the media name comes from the media desc. */ 1950Sstevel@tonic-gate partitions[pos] = cache_get_desc(DM_PARTITION, desc->p.disk, 1960Sstevel@tonic-gate part_name, desc->name, errp); 1970Sstevel@tonic-gate if (*errp != 0) { 1980Sstevel@tonic-gate cache_free_descriptors(partitions); 1990Sstevel@tonic-gate return (NULL); 2000Sstevel@tonic-gate } 2010Sstevel@tonic-gate 2020Sstevel@tonic-gate pos++; 2030Sstevel@tonic-gate } 2040Sstevel@tonic-gate } 2050Sstevel@tonic-gate partitions[pos] = NULL; 2060Sstevel@tonic-gate 2070Sstevel@tonic-gate *errp = 0; 2080Sstevel@tonic-gate return (partitions); 2090Sstevel@tonic-gate } 2100Sstevel@tonic-gate 2110Sstevel@tonic-gate nvlist_t * 2120Sstevel@tonic-gate partition_get_attributes(descriptor_t *dp, int *errp) 2130Sstevel@tonic-gate { 2140Sstevel@tonic-gate nvlist_t *attrs = NULL; 2150Sstevel@tonic-gate struct ipart iparts[FD_NUMPART]; 2160Sstevel@tonic-gate 2170Sstevel@tonic-gate if (!desc_ok(dp)) { 2180Sstevel@tonic-gate *errp = ENODEV; 2190Sstevel@tonic-gate return (NULL); 2200Sstevel@tonic-gate } 2210Sstevel@tonic-gate 2220Sstevel@tonic-gate if ((*errp = get_parts(dp->p.disk, iparts, NULL, 0)) != 0) { 2230Sstevel@tonic-gate return (NULL); 2240Sstevel@tonic-gate } 2250Sstevel@tonic-gate 2260Sstevel@tonic-gate if (nvlist_alloc(&attrs, NVATTRS, 0) != 0) { 2270Sstevel@tonic-gate *errp = ENOMEM; 2280Sstevel@tonic-gate return (NULL); 2290Sstevel@tonic-gate } 2300Sstevel@tonic-gate 2310Sstevel@tonic-gate if ((*errp = get_attrs(dp, iparts, attrs)) != 0) { 2320Sstevel@tonic-gate nvlist_free(attrs); 2330Sstevel@tonic-gate attrs = NULL; 2340Sstevel@tonic-gate } 2350Sstevel@tonic-gate 2360Sstevel@tonic-gate return (attrs); 2370Sstevel@tonic-gate } 2380Sstevel@tonic-gate 2390Sstevel@tonic-gate /* 2400Sstevel@tonic-gate * Look for the partition by the partition number (which is not too useful). 2410Sstevel@tonic-gate */ 2420Sstevel@tonic-gate descriptor_t * 2430Sstevel@tonic-gate partition_get_descriptor_by_name(char *name, int *errp) 2440Sstevel@tonic-gate { 2450Sstevel@tonic-gate descriptor_t **partitions; 2460Sstevel@tonic-gate int i; 2470Sstevel@tonic-gate descriptor_t *partition = NULL; 2480Sstevel@tonic-gate 2490Sstevel@tonic-gate partitions = cache_get_descriptors(DM_PARTITION, errp); 2500Sstevel@tonic-gate if (*errp != 0) { 2510Sstevel@tonic-gate return (NULL); 2520Sstevel@tonic-gate } 2530Sstevel@tonic-gate 2540Sstevel@tonic-gate for (i = 0; partitions[i]; i++) { 2550Sstevel@tonic-gate if (libdiskmgt_str_eq(name, partitions[i]->name)) { 2560Sstevel@tonic-gate partition = partitions[i]; 2570Sstevel@tonic-gate } else { 2580Sstevel@tonic-gate /* clean up the unused descriptors */ 2590Sstevel@tonic-gate cache_free_descriptor(partitions[i]); 2600Sstevel@tonic-gate } 2610Sstevel@tonic-gate } 2620Sstevel@tonic-gate free(partitions); 2630Sstevel@tonic-gate 2640Sstevel@tonic-gate if (partition == NULL) { 2650Sstevel@tonic-gate *errp = ENODEV; 2660Sstevel@tonic-gate } 2670Sstevel@tonic-gate 2680Sstevel@tonic-gate return (partition); 2690Sstevel@tonic-gate } 2700Sstevel@tonic-gate 2710Sstevel@tonic-gate /* ARGSUSED */ 2720Sstevel@tonic-gate descriptor_t ** 2730Sstevel@tonic-gate partition_get_descriptors(int filter[], int *errp) 2740Sstevel@tonic-gate { 2750Sstevel@tonic-gate return (cache_get_descriptors(DM_PARTITION, errp)); 2760Sstevel@tonic-gate } 2770Sstevel@tonic-gate 2780Sstevel@tonic-gate char * 2790Sstevel@tonic-gate partition_get_name(descriptor_t *desc) 2800Sstevel@tonic-gate { 2810Sstevel@tonic-gate return (desc->name); 2820Sstevel@tonic-gate } 2830Sstevel@tonic-gate 2840Sstevel@tonic-gate /* ARGSUSED */ 2850Sstevel@tonic-gate nvlist_t * 2860Sstevel@tonic-gate partition_get_stats(descriptor_t *dp, int stat_type, int *errp) 2870Sstevel@tonic-gate { 2880Sstevel@tonic-gate /* There are no stat types defined for partitions */ 2890Sstevel@tonic-gate *errp = EINVAL; 2900Sstevel@tonic-gate return (NULL); 2910Sstevel@tonic-gate } 2920Sstevel@tonic-gate 2930Sstevel@tonic-gate /* ARGSUSED */ 2940Sstevel@tonic-gate int 2950Sstevel@tonic-gate partition_has_fdisk(disk_t *dp, int fd) 2960Sstevel@tonic-gate { 2970Sstevel@tonic-gate char bootsect[512 * 3]; /* 3 sectors to be safe */ 2980Sstevel@tonic-gate 2990Sstevel@tonic-gate #ifdef sparc 3000Sstevel@tonic-gate if (dp->drv_type == DM_DT_FIXED) { 3010Sstevel@tonic-gate /* on sparc, only removable media can have fdisk parts. */ 3020Sstevel@tonic-gate return (0); 3030Sstevel@tonic-gate } 3040Sstevel@tonic-gate #endif 3050Sstevel@tonic-gate 3060Sstevel@tonic-gate /* 3070Sstevel@tonic-gate * We assume the caller already made sure media was inserted and 3080Sstevel@tonic-gate * spun up. 3090Sstevel@tonic-gate */ 3100Sstevel@tonic-gate 3110Sstevel@tonic-gate if ((ioctl(fd, DKIOCGMBOOT, bootsect) < 0) && (errno != ENOTTY)) { 3120Sstevel@tonic-gate return (0); 3130Sstevel@tonic-gate } 3140Sstevel@tonic-gate 3150Sstevel@tonic-gate return (1); 3160Sstevel@tonic-gate } 3170Sstevel@tonic-gate 3180Sstevel@tonic-gate /* 3190Sstevel@tonic-gate * A partition descriptor points to a disk, the name is the partition number 3200Sstevel@tonic-gate * and the secondary name is the media name. 3210Sstevel@tonic-gate */ 3220Sstevel@tonic-gate int 3230Sstevel@tonic-gate partition_make_descriptors() 3240Sstevel@tonic-gate { 3250Sstevel@tonic-gate int error; 3260Sstevel@tonic-gate disk_t *dp; 3270Sstevel@tonic-gate 3280Sstevel@tonic-gate dp = cache_get_disklist(); 3290Sstevel@tonic-gate while (dp != NULL) { 3300Sstevel@tonic-gate struct ipart iparts[FD_NUMPART]; 3310Sstevel@tonic-gate char pname[MAXPATHLEN]; 3320Sstevel@tonic-gate 3330Sstevel@tonic-gate if (get_parts(dp, iparts, pname, sizeof (pname)) == 0) { 3340Sstevel@tonic-gate int i; 3350Sstevel@tonic-gate char mname[MAXPATHLEN]; 3360Sstevel@tonic-gate int conv_flag = 0; 337767Ssjelinek #if defined(i386) || defined(__amd64) 3380Sstevel@tonic-gate /* convert part. name (e.g. c0d0p0) */ 3390Sstevel@tonic-gate int len; 3400Sstevel@tonic-gate 3410Sstevel@tonic-gate len = strlen(pname); 3420Sstevel@tonic-gate if (len > 1 && *(pname + (len - 2)) == 'p') { 3430Sstevel@tonic-gate conv_flag = 1; 3440Sstevel@tonic-gate *(pname + (len - 1)) = 0; 3450Sstevel@tonic-gate } 3460Sstevel@tonic-gate #endif 3470Sstevel@tonic-gate 3480Sstevel@tonic-gate mname[0] = 0; 3490Sstevel@tonic-gate (void) media_read_name(dp, mname, sizeof (mname)); 3500Sstevel@tonic-gate 3510Sstevel@tonic-gate for (i = 0; i < FD_NUMPART; i++) { 3520Sstevel@tonic-gate if (iparts[i].systid != 0) { 3530Sstevel@tonic-gate char part_name[MAXPATHLEN]; 3540Sstevel@tonic-gate 3550Sstevel@tonic-gate if (conv_flag) { 3560Sstevel@tonic-gate /* convert part. name (e.g. c0d0p0) */ 3570Sstevel@tonic-gate (void) snprintf(part_name, sizeof (part_name), 3580Sstevel@tonic-gate "%s%d", pname, i); 3590Sstevel@tonic-gate } else { 3600Sstevel@tonic-gate (void) snprintf(part_name, sizeof (part_name), 3610Sstevel@tonic-gate "%d", i); 3620Sstevel@tonic-gate } 3630Sstevel@tonic-gate 3640Sstevel@tonic-gate cache_load_desc(DM_PARTITION, dp, part_name, mname, 3650Sstevel@tonic-gate &error); 3660Sstevel@tonic-gate if (error != 0) { 3670Sstevel@tonic-gate return (error); 3680Sstevel@tonic-gate } 3690Sstevel@tonic-gate } 3700Sstevel@tonic-gate } 3710Sstevel@tonic-gate } 3720Sstevel@tonic-gate dp = dp->next; 3730Sstevel@tonic-gate } 3740Sstevel@tonic-gate 3750Sstevel@tonic-gate return (0); 3760Sstevel@tonic-gate } 3770Sstevel@tonic-gate 3780Sstevel@tonic-gate static int 3790Sstevel@tonic-gate get_attrs(descriptor_t *dp, struct ipart *iparts, nvlist_t *attrs) 3800Sstevel@tonic-gate { 3810Sstevel@tonic-gate char *p; 3820Sstevel@tonic-gate int part_num; 3830Sstevel@tonic-gate 3840Sstevel@tonic-gate /* 3850Sstevel@tonic-gate * We already made sure the media was loaded and ready in the 3860Sstevel@tonic-gate * get_parts call within partition_get_attributes. 3870Sstevel@tonic-gate */ 3880Sstevel@tonic-gate 3890Sstevel@tonic-gate p = strrchr(dp->name, 'p'); 3900Sstevel@tonic-gate if (p == NULL) { 3910Sstevel@tonic-gate p = dp->name; 3920Sstevel@tonic-gate } else { 3930Sstevel@tonic-gate p++; 3940Sstevel@tonic-gate } 3950Sstevel@tonic-gate part_num = atoi(p); 3960Sstevel@tonic-gate if (part_num >= FD_NUMPART || iparts[part_num].systid == 0) { 3970Sstevel@tonic-gate return (ENODEV); 3980Sstevel@tonic-gate } 3990Sstevel@tonic-gate 4000Sstevel@tonic-gate /* we found the partition */ 4010Sstevel@tonic-gate 4020Sstevel@tonic-gate if (nvlist_add_uint32(attrs, DM_BOOTID, 4030Sstevel@tonic-gate (unsigned int)iparts[part_num].bootid) != 0) { 4040Sstevel@tonic-gate return (ENOMEM); 4050Sstevel@tonic-gate } 4060Sstevel@tonic-gate 4070Sstevel@tonic-gate if (nvlist_add_uint32(attrs, DM_PTYPE, 4080Sstevel@tonic-gate (unsigned int)iparts[part_num].systid) != 0) { 4090Sstevel@tonic-gate return (ENOMEM); 4100Sstevel@tonic-gate } 4110Sstevel@tonic-gate 4120Sstevel@tonic-gate if (nvlist_add_uint32(attrs, DM_BHEAD, 4130Sstevel@tonic-gate (unsigned int)iparts[part_num].beghead) != 0) { 4140Sstevel@tonic-gate return (ENOMEM); 4150Sstevel@tonic-gate } 4160Sstevel@tonic-gate 4170Sstevel@tonic-gate if (nvlist_add_uint32(attrs, DM_BSECT, 4180Sstevel@tonic-gate (unsigned int)((iparts[part_num].begsect) & 0x3f)) != 0) { 4190Sstevel@tonic-gate return (ENOMEM); 4200Sstevel@tonic-gate } 4210Sstevel@tonic-gate 4220Sstevel@tonic-gate if (nvlist_add_uint32(attrs, DM_BCYL, (unsigned int) 4230Sstevel@tonic-gate ((iparts[part_num].begcyl & 0xff) | 4240Sstevel@tonic-gate ((iparts[part_num].begsect & 0xc0) << 2))) != 0) { 4250Sstevel@tonic-gate return (ENOMEM); 4260Sstevel@tonic-gate } 4270Sstevel@tonic-gate 4280Sstevel@tonic-gate if (nvlist_add_uint32(attrs, DM_EHEAD, 4290Sstevel@tonic-gate (unsigned int)iparts[part_num].endhead) != 0) { 4300Sstevel@tonic-gate return (ENOMEM); 4310Sstevel@tonic-gate } 4320Sstevel@tonic-gate 4330Sstevel@tonic-gate if (nvlist_add_uint32(attrs, DM_ESECT, 4340Sstevel@tonic-gate (unsigned int)((iparts[part_num].endsect) & 0x3f)) != 0) { 4350Sstevel@tonic-gate return (ENOMEM); 4360Sstevel@tonic-gate } 4370Sstevel@tonic-gate 4380Sstevel@tonic-gate if (nvlist_add_uint32(attrs, DM_ECYL, (unsigned int) 4390Sstevel@tonic-gate ((iparts[part_num].endcyl & 0xff) | 4400Sstevel@tonic-gate ((iparts[part_num].endsect & 0xc0) << 2))) != 0) { 4410Sstevel@tonic-gate return (ENOMEM); 4420Sstevel@tonic-gate } 4430Sstevel@tonic-gate 4440Sstevel@tonic-gate if (nvlist_add_uint32(attrs, DM_RELSECT, 4450Sstevel@tonic-gate (unsigned int)iparts[part_num].relsect) != 0) { 4460Sstevel@tonic-gate return (ENOMEM); 4470Sstevel@tonic-gate } 4480Sstevel@tonic-gate 4490Sstevel@tonic-gate if (nvlist_add_uint32(attrs, DM_NSECTORS, 4500Sstevel@tonic-gate (unsigned int)iparts[part_num].numsect) != 0) { 4510Sstevel@tonic-gate return (ENOMEM); 4520Sstevel@tonic-gate } 4530Sstevel@tonic-gate 4540Sstevel@tonic-gate return (0); 4550Sstevel@tonic-gate } 4560Sstevel@tonic-gate 4570Sstevel@tonic-gate static int 4580Sstevel@tonic-gate get_parts(disk_t *disk, struct ipart *iparts, char *opath, int opath_len) 4590Sstevel@tonic-gate { 4600Sstevel@tonic-gate int fd; 4610Sstevel@tonic-gate struct dk_minfo minfo; 4620Sstevel@tonic-gate struct mboot bootblk; 4630Sstevel@tonic-gate char bootsect[512]; 4640Sstevel@tonic-gate int i; 4650Sstevel@tonic-gate 4660Sstevel@tonic-gate /* Can't use drive_open_disk since we need the partition dev name. */ 4670Sstevel@tonic-gate if ((fd = open_disk(disk, opath, opath_len)) < 0) { 4680Sstevel@tonic-gate return (ENODEV); 4690Sstevel@tonic-gate } 4700Sstevel@tonic-gate 4710Sstevel@tonic-gate /* First make sure media is inserted and spun up. */ 4720Sstevel@tonic-gate if (!media_read_info(fd, &minfo)) { 4730Sstevel@tonic-gate (void) close(fd); 4740Sstevel@tonic-gate return (ENODEV); 4750Sstevel@tonic-gate } 4760Sstevel@tonic-gate 4770Sstevel@tonic-gate if (!partition_has_fdisk(disk, fd)) { 4780Sstevel@tonic-gate (void) close(fd); 4790Sstevel@tonic-gate return (ENOTTY); 4800Sstevel@tonic-gate } 4810Sstevel@tonic-gate 4820Sstevel@tonic-gate if (lseek(fd, 0, 0) == -1) { 4830Sstevel@tonic-gate (void) close(fd); 4840Sstevel@tonic-gate return (ENODEV); 4850Sstevel@tonic-gate } 4860Sstevel@tonic-gate 4870Sstevel@tonic-gate if (read(fd, bootsect, 512) != 512) { 4880Sstevel@tonic-gate (void) close(fd); 4890Sstevel@tonic-gate return (ENODEV); 4900Sstevel@tonic-gate } 4910Sstevel@tonic-gate (void) close(fd); 4920Sstevel@tonic-gate 4930Sstevel@tonic-gate (void) memcpy(&bootblk, bootsect, sizeof (bootblk)); 4940Sstevel@tonic-gate 4950Sstevel@tonic-gate if (les(bootblk.signature) != MBB_MAGIC) { 4960Sstevel@tonic-gate return (ENOTTY); 4970Sstevel@tonic-gate } 4980Sstevel@tonic-gate 4990Sstevel@tonic-gate (void) memcpy(iparts, bootblk.parts, ISIZE); 5000Sstevel@tonic-gate 5010Sstevel@tonic-gate for (i = 0; i < FD_NUMPART; i++) { 5020Sstevel@tonic-gate if (iparts[i].systid != 0) { 5030Sstevel@tonic-gate iparts[i].relsect = lel(iparts[i].relsect); 5040Sstevel@tonic-gate iparts[i].numsect = lel(iparts[i].numsect); 5050Sstevel@tonic-gate } 5060Sstevel@tonic-gate } 5070Sstevel@tonic-gate 5080Sstevel@tonic-gate return (0); 5090Sstevel@tonic-gate } 5100Sstevel@tonic-gate /* return 1 if the partition descriptor is still valid, 0 if not. */ 5110Sstevel@tonic-gate static int 5120Sstevel@tonic-gate desc_ok(descriptor_t *dp) 5130Sstevel@tonic-gate { 5140Sstevel@tonic-gate /* First verify the media name for removable media */ 5150Sstevel@tonic-gate if (dp->p.disk->removable) { 5160Sstevel@tonic-gate char mname[MAXPATHLEN]; 5170Sstevel@tonic-gate 5180Sstevel@tonic-gate if (!media_read_name(dp->p.disk, mname, sizeof (mname))) { 5190Sstevel@tonic-gate return (0); 5200Sstevel@tonic-gate } 5210Sstevel@tonic-gate 5220Sstevel@tonic-gate if (mname[0] == 0) { 5230Sstevel@tonic-gate return (libdiskmgt_str_eq(dp->secondary_name, NULL)); 5240Sstevel@tonic-gate } else { 5250Sstevel@tonic-gate return (libdiskmgt_str_eq(dp->secondary_name, mname)); 5260Sstevel@tonic-gate } 5270Sstevel@tonic-gate } 5280Sstevel@tonic-gate 5290Sstevel@tonic-gate /* 5300Sstevel@tonic-gate * We could verify the partition is still there but this is kind of 5310Sstevel@tonic-gate * expensive and other code down the line will do that (e.g. see 5320Sstevel@tonic-gate * get_attrs). 5330Sstevel@tonic-gate */ 5340Sstevel@tonic-gate 5350Sstevel@tonic-gate return (1); 5360Sstevel@tonic-gate } 5370Sstevel@tonic-gate 5380Sstevel@tonic-gate /* 5390Sstevel@tonic-gate * Return 1 if partition has slices, 0 if not. 5400Sstevel@tonic-gate */ 5410Sstevel@tonic-gate static int 5420Sstevel@tonic-gate has_slices(descriptor_t *desc, int *errp) 5430Sstevel@tonic-gate { 5440Sstevel@tonic-gate int pnum; 5450Sstevel@tonic-gate int i; 5460Sstevel@tonic-gate char *p; 5470Sstevel@tonic-gate struct ipart iparts[FD_NUMPART]; 5480Sstevel@tonic-gate 5490Sstevel@tonic-gate if (get_parts(desc->p.disk, iparts, NULL, 0) != 0) { 5500Sstevel@tonic-gate *errp = ENODEV; 5510Sstevel@tonic-gate return (0); 5520Sstevel@tonic-gate } 5530Sstevel@tonic-gate 5540Sstevel@tonic-gate p = strrchr(desc->name, 'p'); 5550Sstevel@tonic-gate if (p == NULL) { 5560Sstevel@tonic-gate p = desc->name; 5570Sstevel@tonic-gate } else { 5580Sstevel@tonic-gate p++; 5590Sstevel@tonic-gate } 5600Sstevel@tonic-gate pnum = atoi(p); 5610Sstevel@tonic-gate 5620Sstevel@tonic-gate /* 5630Sstevel@tonic-gate * Slices are associated with the active solaris partition or if there 5640Sstevel@tonic-gate * is no active solaris partition, then the first solaris partition. 5650Sstevel@tonic-gate */ 5660Sstevel@tonic-gate 5670Sstevel@tonic-gate *errp = 0; 5680Sstevel@tonic-gate if (iparts[pnum].bootid == ACTIVE && 5690Sstevel@tonic-gate (iparts[pnum].systid == SUNIXOS || 5700Sstevel@tonic-gate iparts[pnum].systid == SUNIXOS2)) { 5710Sstevel@tonic-gate return (1); 5720Sstevel@tonic-gate } else { 5730Sstevel@tonic-gate int active = 0; 5740Sstevel@tonic-gate 5750Sstevel@tonic-gate /* Check if there are no active solaris partitions. */ 5760Sstevel@tonic-gate for (i = 0; i < FD_NUMPART; i++) { 5770Sstevel@tonic-gate if (iparts[i].bootid == ACTIVE && 5780Sstevel@tonic-gate (iparts[i].systid == SUNIXOS || 5790Sstevel@tonic-gate iparts[i].systid == SUNIXOS2)) { 5800Sstevel@tonic-gate active = 1; 5810Sstevel@tonic-gate break; 5820Sstevel@tonic-gate } 5830Sstevel@tonic-gate } 5840Sstevel@tonic-gate 5850Sstevel@tonic-gate if (!active) { 5860Sstevel@tonic-gate /* Check if this is the first solaris partition. */ 5870Sstevel@tonic-gate for (i = 0; i < FD_NUMPART; i++) { 5880Sstevel@tonic-gate if (iparts[i].systid == SUNIXOS || 5890Sstevel@tonic-gate iparts[i].systid == SUNIXOS2) { 5900Sstevel@tonic-gate break; 5910Sstevel@tonic-gate } 5920Sstevel@tonic-gate } 5930Sstevel@tonic-gate 5940Sstevel@tonic-gate if (i < FD_NUMPART && i == pnum) { 5950Sstevel@tonic-gate return (1); 5960Sstevel@tonic-gate } 5970Sstevel@tonic-gate } 5980Sstevel@tonic-gate } 5990Sstevel@tonic-gate 6000Sstevel@tonic-gate return (0); 6010Sstevel@tonic-gate } 6020Sstevel@tonic-gate 6030Sstevel@tonic-gate static int 6040Sstevel@tonic-gate open_disk(disk_t *diskp, char *opath, int len) 6050Sstevel@tonic-gate { 6060Sstevel@tonic-gate /* 607*2912Sartem * Just open the first devpath. 6080Sstevel@tonic-gate */ 6090Sstevel@tonic-gate if (diskp->aliases != NULL && diskp->aliases->devpaths != NULL) { 6100Sstevel@tonic-gate #ifdef sparc 6110Sstevel@tonic-gate if (opath != NULL) { 6120Sstevel@tonic-gate (void) strlcpy(opath, diskp->aliases->devpaths->devpath, len); 6130Sstevel@tonic-gate } 6140Sstevel@tonic-gate return (open(diskp->aliases->devpaths->devpath, O_RDONLY|O_NDELAY)); 6150Sstevel@tonic-gate #else 6160Sstevel@tonic-gate /* On intel we need to open partition device (e.g. c0d0p0). */ 6170Sstevel@tonic-gate char part_dev[MAXPATHLEN]; 6180Sstevel@tonic-gate char *p; 6190Sstevel@tonic-gate 6200Sstevel@tonic-gate (void) strlcpy(part_dev, diskp->aliases->devpaths->devpath, 6210Sstevel@tonic-gate sizeof (part_dev)); 6220Sstevel@tonic-gate p = strrchr(part_dev, '/'); 6230Sstevel@tonic-gate if (p == NULL) { 6240Sstevel@tonic-gate p = strrchr(part_dev, 's'); 6250Sstevel@tonic-gate if (p != NULL) { 6260Sstevel@tonic-gate *p = 'p'; 6270Sstevel@tonic-gate } 6280Sstevel@tonic-gate } else { 6290Sstevel@tonic-gate char *ps; 6300Sstevel@tonic-gate 6310Sstevel@tonic-gate *p = 0; 6320Sstevel@tonic-gate ps = strrchr((p + 1), 's'); 6330Sstevel@tonic-gate if (ps != NULL) { 6340Sstevel@tonic-gate *ps = 'p'; 6350Sstevel@tonic-gate } 6360Sstevel@tonic-gate *p = '/'; 6370Sstevel@tonic-gate } 6380Sstevel@tonic-gate 6390Sstevel@tonic-gate if (opath != NULL) { 6400Sstevel@tonic-gate (void) strlcpy(opath, part_dev, len); 6410Sstevel@tonic-gate } 6420Sstevel@tonic-gate return (open(part_dev, O_RDONLY|O_NDELAY)); 6430Sstevel@tonic-gate #endif 6440Sstevel@tonic-gate } 6450Sstevel@tonic-gate 6460Sstevel@tonic-gate return (-1); 6470Sstevel@tonic-gate } 648