1*bb9b6b3fSSheshadri Vasudevan /* 2*bb9b6b3fSSheshadri Vasudevan * CDDL HEADER START 3*bb9b6b3fSSheshadri Vasudevan * 4*bb9b6b3fSSheshadri Vasudevan * The contents of this file are subject to the terms of the 5*bb9b6b3fSSheshadri Vasudevan * Common Development and Distribution License (the "License"). 6*bb9b6b3fSSheshadri Vasudevan * You may not use this file except in compliance with the License. 7*bb9b6b3fSSheshadri Vasudevan * 8*bb9b6b3fSSheshadri Vasudevan * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*bb9b6b3fSSheshadri Vasudevan * or http://www.opensolaris.org/os/licensing. 10*bb9b6b3fSSheshadri Vasudevan * See the License for the specific language governing permissions 11*bb9b6b3fSSheshadri Vasudevan * and limitations under the License. 12*bb9b6b3fSSheshadri Vasudevan * 13*bb9b6b3fSSheshadri Vasudevan * When distributing Covered Code, include this CDDL HEADER in each 14*bb9b6b3fSSheshadri Vasudevan * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*bb9b6b3fSSheshadri Vasudevan * If applicable, add the following below this CDDL HEADER, with the 16*bb9b6b3fSSheshadri Vasudevan * fields enclosed by brackets "[]" replaced with your own identifying 17*bb9b6b3fSSheshadri Vasudevan * information: Portions Copyright [yyyy] [name of copyright owner] 18*bb9b6b3fSSheshadri Vasudevan * 19*bb9b6b3fSSheshadri Vasudevan * CDDL HEADER END 20*bb9b6b3fSSheshadri Vasudevan */ 21*bb9b6b3fSSheshadri Vasudevan /* 22*bb9b6b3fSSheshadri Vasudevan * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23*bb9b6b3fSSheshadri Vasudevan * Use is subject to license terms. 24*bb9b6b3fSSheshadri Vasudevan */ 25*bb9b6b3fSSheshadri Vasudevan 26*bb9b6b3fSSheshadri Vasudevan #include <stdio.h> 27*bb9b6b3fSSheshadri Vasudevan #include <stdlib.h> 28*bb9b6b3fSSheshadri Vasudevan #include <string.h> 29*bb9b6b3fSSheshadri Vasudevan #include <strings.h> 30*bb9b6b3fSSheshadri Vasudevan #include <unistd.h> 31*bb9b6b3fSSheshadri Vasudevan #include <errno.h> 32*bb9b6b3fSSheshadri Vasudevan #include <fcntl.h> 33*bb9b6b3fSSheshadri Vasudevan #include <ctype.h> 34*bb9b6b3fSSheshadri Vasudevan #include <sys/stat.h> 35*bb9b6b3fSSheshadri Vasudevan #include <sys/types.h> 36*bb9b6b3fSSheshadri Vasudevan #include <sys/param.h> 37*bb9b6b3fSSheshadri Vasudevan #include <sys/systeminfo.h> 38*bb9b6b3fSSheshadri Vasudevan #include <sys/efi_partition.h> 39*bb9b6b3fSSheshadri Vasudevan #include <sys/byteorder.h> 40*bb9b6b3fSSheshadri Vasudevan 41*bb9b6b3fSSheshadri Vasudevan #include <sys/vtoc.h> 42*bb9b6b3fSSheshadri Vasudevan #include <sys/tty.h> 43*bb9b6b3fSSheshadri Vasudevan #include <sys/dktp/fdisk.h> 44*bb9b6b3fSSheshadri Vasudevan #include <sys/dkio.h> 45*bb9b6b3fSSheshadri Vasudevan #include <sys/mnttab.h> 46*bb9b6b3fSSheshadri Vasudevan #include "libfdisk.h" 47*bb9b6b3fSSheshadri Vasudevan 48*bb9b6b3fSSheshadri Vasudevan #define DEFAULT_PATH_PREFIX "/dev/rdsk/" 49*bb9b6b3fSSheshadri Vasudevan 50*bb9b6b3fSSheshadri Vasudevan static void fdisk_free_ld_nodes(ext_part_t *epp); 51*bb9b6b3fSSheshadri Vasudevan static void fdisk_ext_place_in_sorted_list(ext_part_t *epp, 52*bb9b6b3fSSheshadri Vasudevan logical_drive_t *newld); 53*bb9b6b3fSSheshadri Vasudevan static void fdisk_ext_remove_from_sorted_list(ext_part_t *epp, 54*bb9b6b3fSSheshadri Vasudevan logical_drive_t *delld); 55*bb9b6b3fSSheshadri Vasudevan static int fdisk_ext_overlapping_parts(ext_part_t *epp, uint32_t begsec, 56*bb9b6b3fSSheshadri Vasudevan uint32_t endsec); 57*bb9b6b3fSSheshadri Vasudevan static int fdisk_read_extpart(ext_part_t *epp); 58*bb9b6b3fSSheshadri Vasudevan static void fdisk_set_CHS_values(ext_part_t *epp, struct ipart *part); 59*bb9b6b3fSSheshadri Vasudevan static int fdisk_init_master_part_table(ext_part_t *epp); 60*bb9b6b3fSSheshadri Vasudevan static struct ipart *fdisk_alloc_part_table(); 61*bb9b6b3fSSheshadri Vasudevan static int fdisk_read_master_part_table(ext_part_t *epp); 62*bb9b6b3fSSheshadri Vasudevan 63*bb9b6b3fSSheshadri Vasudevan static int 64*bb9b6b3fSSheshadri Vasudevan fdisk_init_disk_geom(ext_part_t *epp) 65*bb9b6b3fSSheshadri Vasudevan { 66*bb9b6b3fSSheshadri Vasudevan struct dk_geom disk_geom; 67*bb9b6b3fSSheshadri Vasudevan struct dk_minfo disk_info; 68*bb9b6b3fSSheshadri Vasudevan int no_virtgeom_ioctl = 0, no_physgeom_ioctl = 0; 69*bb9b6b3fSSheshadri Vasudevan 70*bb9b6b3fSSheshadri Vasudevan /* Get disk's HBA (virtual) geometry */ 71*bb9b6b3fSSheshadri Vasudevan errno = 0; 72*bb9b6b3fSSheshadri Vasudevan if (ioctl(epp->dev_fd, DKIOCG_VIRTGEOM, &disk_geom)) { 73*bb9b6b3fSSheshadri Vasudevan if (errno == ENOTTY) { 74*bb9b6b3fSSheshadri Vasudevan no_virtgeom_ioctl = 1; 75*bb9b6b3fSSheshadri Vasudevan } else if (errno == EINVAL) { 76*bb9b6b3fSSheshadri Vasudevan /* 77*bb9b6b3fSSheshadri Vasudevan * This means that the ioctl exists, but 78*bb9b6b3fSSheshadri Vasudevan * is invalid for this disk, meaning the 79*bb9b6b3fSSheshadri Vasudevan * disk doesn't have an HBA geometry 80*bb9b6b3fSSheshadri Vasudevan * (like, say, it's larger than 8GB). 81*bb9b6b3fSSheshadri Vasudevan */ 82*bb9b6b3fSSheshadri Vasudevan epp->disk_geom.virt_cyl = epp->disk_geom.virt_heads = 83*bb9b6b3fSSheshadri Vasudevan epp->disk_geom.virt_sec = 0; 84*bb9b6b3fSSheshadri Vasudevan } else { 85*bb9b6b3fSSheshadri Vasudevan return (FDISK_ENOVGEOM); 86*bb9b6b3fSSheshadri Vasudevan } 87*bb9b6b3fSSheshadri Vasudevan } else { 88*bb9b6b3fSSheshadri Vasudevan /* save virtual geometry values obtained by ioctl */ 89*bb9b6b3fSSheshadri Vasudevan epp->disk_geom.virt_cyl = disk_geom.dkg_ncyl; 90*bb9b6b3fSSheshadri Vasudevan epp->disk_geom.virt_heads = disk_geom.dkg_nhead; 91*bb9b6b3fSSheshadri Vasudevan epp->disk_geom.virt_sec = disk_geom.dkg_nsect; 92*bb9b6b3fSSheshadri Vasudevan } 93*bb9b6b3fSSheshadri Vasudevan 94*bb9b6b3fSSheshadri Vasudevan errno = 0; 95*bb9b6b3fSSheshadri Vasudevan if (ioctl(epp->dev_fd, DKIOCG_PHYGEOM, &disk_geom)) { 96*bb9b6b3fSSheshadri Vasudevan if (errno == ENOTTY) { 97*bb9b6b3fSSheshadri Vasudevan no_physgeom_ioctl = 1; 98*bb9b6b3fSSheshadri Vasudevan } else { 99*bb9b6b3fSSheshadri Vasudevan return (FDISK_ENOPGEOM); 100*bb9b6b3fSSheshadri Vasudevan } 101*bb9b6b3fSSheshadri Vasudevan } 102*bb9b6b3fSSheshadri Vasudevan /* 103*bb9b6b3fSSheshadri Vasudevan * Call DKIOCGGEOM if the ioctls for physical and virtual 104*bb9b6b3fSSheshadri Vasudevan * geometry fail. Get both from this generic call. 105*bb9b6b3fSSheshadri Vasudevan */ 106*bb9b6b3fSSheshadri Vasudevan if (no_virtgeom_ioctl && no_physgeom_ioctl) { 107*bb9b6b3fSSheshadri Vasudevan errno = 0; 108*bb9b6b3fSSheshadri Vasudevan if (ioctl(epp->dev_fd, DKIOCGGEOM, &disk_geom)) { 109*bb9b6b3fSSheshadri Vasudevan return (FDISK_ENOLGEOM); 110*bb9b6b3fSSheshadri Vasudevan } 111*bb9b6b3fSSheshadri Vasudevan } 112*bb9b6b3fSSheshadri Vasudevan 113*bb9b6b3fSSheshadri Vasudevan epp->disk_geom.phys_cyl = disk_geom.dkg_ncyl; 114*bb9b6b3fSSheshadri Vasudevan epp->disk_geom.phys_heads = disk_geom.dkg_nhead; 115*bb9b6b3fSSheshadri Vasudevan epp->disk_geom.phys_sec = disk_geom.dkg_nsect; 116*bb9b6b3fSSheshadri Vasudevan epp->disk_geom.alt_cyl = disk_geom.dkg_acyl; 117*bb9b6b3fSSheshadri Vasudevan 118*bb9b6b3fSSheshadri Vasudevan /* 119*bb9b6b3fSSheshadri Vasudevan * If DKIOCGMEDIAINFO ioctl succeeds, set the dki_lbsize as the 120*bb9b6b3fSSheshadri Vasudevan * size of the sector, else default to 512 121*bb9b6b3fSSheshadri Vasudevan */ 122*bb9b6b3fSSheshadri Vasudevan if (ioctl(epp->dev_fd, DKIOCGMEDIAINFO, (caddr_t)&disk_info) < 0) { 123*bb9b6b3fSSheshadri Vasudevan /* ioctl failed, falling back to default value of 512 bytes */ 124*bb9b6b3fSSheshadri Vasudevan epp->disk_geom.sectsize = 512; 125*bb9b6b3fSSheshadri Vasudevan } else { 126*bb9b6b3fSSheshadri Vasudevan epp->disk_geom.sectsize = ((disk_info.dki_lbsize) ? 127*bb9b6b3fSSheshadri Vasudevan disk_info.dki_lbsize : 512); 128*bb9b6b3fSSheshadri Vasudevan } 129*bb9b6b3fSSheshadri Vasudevan 130*bb9b6b3fSSheshadri Vasudevan /* 131*bb9b6b3fSSheshadri Vasudevan * if hba geometry was not set by DKIOC_VIRTGEOM 132*bb9b6b3fSSheshadri Vasudevan * or we got an invalid hba geometry 133*bb9b6b3fSSheshadri Vasudevan * then set hba geometry based on max values 134*bb9b6b3fSSheshadri Vasudevan */ 135*bb9b6b3fSSheshadri Vasudevan if (no_virtgeom_ioctl || disk_geom.dkg_ncyl == 0 || 136*bb9b6b3fSSheshadri Vasudevan disk_geom.dkg_nhead == 0 || disk_geom.dkg_nsect == 0 || 137*bb9b6b3fSSheshadri Vasudevan disk_geom.dkg_ncyl > MAX_CYL || disk_geom.dkg_nhead > MAX_HEAD || 138*bb9b6b3fSSheshadri Vasudevan disk_geom.dkg_nsect > MAX_SECT) { 139*bb9b6b3fSSheshadri Vasudevan epp->disk_geom.virt_sec = MAX_SECT; 140*bb9b6b3fSSheshadri Vasudevan epp->disk_geom.virt_heads = MAX_HEAD + 1; 141*bb9b6b3fSSheshadri Vasudevan epp->disk_geom.virt_cyl = (epp->disk_geom.phys_cyl * 142*bb9b6b3fSSheshadri Vasudevan epp->disk_geom.phys_heads * epp->disk_geom.phys_sec) / 143*bb9b6b3fSSheshadri Vasudevan (epp->disk_geom.virt_sec * epp->disk_geom.virt_heads); 144*bb9b6b3fSSheshadri Vasudevan } 145*bb9b6b3fSSheshadri Vasudevan return (FDISK_SUCCESS); 146*bb9b6b3fSSheshadri Vasudevan } 147*bb9b6b3fSSheshadri Vasudevan 148*bb9b6b3fSSheshadri Vasudevan /* 149*bb9b6b3fSSheshadri Vasudevan * Initialise important members of the ext_part_t structure and 150*bb9b6b3fSSheshadri Vasudevan * other data structures vital to functionality of libfdisk 151*bb9b6b3fSSheshadri Vasudevan */ 152*bb9b6b3fSSheshadri Vasudevan int 153*bb9b6b3fSSheshadri Vasudevan libfdisk_init(ext_part_t **epp, char *devstr, struct ipart *parttab, int opflag) 154*bb9b6b3fSSheshadri Vasudevan { 155*bb9b6b3fSSheshadri Vasudevan ext_part_t *temp; 156*bb9b6b3fSSheshadri Vasudevan struct stat sbuf; 157*bb9b6b3fSSheshadri Vasudevan int rval = FDISK_SUCCESS; 158*bb9b6b3fSSheshadri Vasudevan 159*bb9b6b3fSSheshadri Vasudevan if ((temp = calloc(1, sizeof (ext_part_t))) == NULL) { 160*bb9b6b3fSSheshadri Vasudevan return (ENOMEM); 161*bb9b6b3fSSheshadri Vasudevan } 162*bb9b6b3fSSheshadri Vasudevan 163*bb9b6b3fSSheshadri Vasudevan (void) strncpy(temp->device_name, devstr, 164*bb9b6b3fSSheshadri Vasudevan sizeof (temp->device_name)); 165*bb9b6b3fSSheshadri Vasudevan 166*bb9b6b3fSSheshadri Vasudevan /* Try to stat the node as provided */ 167*bb9b6b3fSSheshadri Vasudevan if (stat(temp->device_name, &sbuf) != 0) { 168*bb9b6b3fSSheshadri Vasudevan 169*bb9b6b3fSSheshadri Vasudevan /* Prefix /dev/rdsk/ and stat again */ 170*bb9b6b3fSSheshadri Vasudevan (void) snprintf(temp->device_name, sizeof (temp->device_name), 171*bb9b6b3fSSheshadri Vasudevan "%s%s", DEFAULT_PATH_PREFIX, devstr); 172*bb9b6b3fSSheshadri Vasudevan 173*bb9b6b3fSSheshadri Vasudevan if (stat(temp->device_name, &sbuf) != 0) { 174*bb9b6b3fSSheshadri Vasudevan 175*bb9b6b3fSSheshadri Vasudevan /* 176*bb9b6b3fSSheshadri Vasudevan * In case of an EFI labeled disk, the device name 177*bb9b6b3fSSheshadri Vasudevan * could be cN[tN]dN. There is no pN. So we add "p0" 178*bb9b6b3fSSheshadri Vasudevan * at the end if we do not find it and stat again. 179*bb9b6b3fSSheshadri Vasudevan */ 180*bb9b6b3fSSheshadri Vasudevan if (strrchr(temp->device_name, 'p') == NULL) { 181*bb9b6b3fSSheshadri Vasudevan (void) strcat(temp->device_name, "p0"); 182*bb9b6b3fSSheshadri Vasudevan } 183*bb9b6b3fSSheshadri Vasudevan 184*bb9b6b3fSSheshadri Vasudevan if (stat(temp->device_name, &sbuf) != 0) { 185*bb9b6b3fSSheshadri Vasudevan 186*bb9b6b3fSSheshadri Vasudevan /* Failed all options, give up */ 187*bb9b6b3fSSheshadri Vasudevan free(temp); 188*bb9b6b3fSSheshadri Vasudevan return (EINVAL); 189*bb9b6b3fSSheshadri Vasudevan } 190*bb9b6b3fSSheshadri Vasudevan } 191*bb9b6b3fSSheshadri Vasudevan } 192*bb9b6b3fSSheshadri Vasudevan 193*bb9b6b3fSSheshadri Vasudevan /* Make sure the device is a raw device */ 194*bb9b6b3fSSheshadri Vasudevan if ((sbuf.st_mode & S_IFMT) != S_IFCHR) { 195*bb9b6b3fSSheshadri Vasudevan return (EINVAL); 196*bb9b6b3fSSheshadri Vasudevan } 197*bb9b6b3fSSheshadri Vasudevan 198*bb9b6b3fSSheshadri Vasudevan temp->ld_head = NULL; 199*bb9b6b3fSSheshadri Vasudevan temp->sorted_ld_head = NULL; 200*bb9b6b3fSSheshadri Vasudevan 201*bb9b6b3fSSheshadri Vasudevan if ((temp->dev_fd = open(temp->device_name, O_RDWR, 0666)) < 0) { 202*bb9b6b3fSSheshadri Vasudevan free(temp); 203*bb9b6b3fSSheshadri Vasudevan return (EINVAL); 204*bb9b6b3fSSheshadri Vasudevan } 205*bb9b6b3fSSheshadri Vasudevan 206*bb9b6b3fSSheshadri Vasudevan if ((temp->mtable = parttab) == NULL) { 207*bb9b6b3fSSheshadri Vasudevan if ((rval = fdisk_init_master_part_table(temp)) != 208*bb9b6b3fSSheshadri Vasudevan FDISK_SUCCESS) { 209*bb9b6b3fSSheshadri Vasudevan return (rval); 210*bb9b6b3fSSheshadri Vasudevan } 211*bb9b6b3fSSheshadri Vasudevan } 212*bb9b6b3fSSheshadri Vasudevan 213*bb9b6b3fSSheshadri Vasudevan temp->op_flag = opflag; 214*bb9b6b3fSSheshadri Vasudevan 215*bb9b6b3fSSheshadri Vasudevan if ((rval = fdisk_init_disk_geom(temp)) != FDISK_SUCCESS) { 216*bb9b6b3fSSheshadri Vasudevan return (rval); 217*bb9b6b3fSSheshadri Vasudevan } 218*bb9b6b3fSSheshadri Vasudevan 219*bb9b6b3fSSheshadri Vasudevan *epp = temp; 220*bb9b6b3fSSheshadri Vasudevan 221*bb9b6b3fSSheshadri Vasudevan if (opflag & FDISK_READ_DISK) { 222*bb9b6b3fSSheshadri Vasudevan rval = fdisk_read_extpart(*epp); 223*bb9b6b3fSSheshadri Vasudevan } 224*bb9b6b3fSSheshadri Vasudevan return (rval); 225*bb9b6b3fSSheshadri Vasudevan } 226*bb9b6b3fSSheshadri Vasudevan 227*bb9b6b3fSSheshadri Vasudevan int 228*bb9b6b3fSSheshadri Vasudevan libfdisk_reset(ext_part_t *epp) 229*bb9b6b3fSSheshadri Vasudevan { 230*bb9b6b3fSSheshadri Vasudevan int rval = FDISK_SUCCESS; 231*bb9b6b3fSSheshadri Vasudevan 232*bb9b6b3fSSheshadri Vasudevan fdisk_free_ld_nodes(epp); 233*bb9b6b3fSSheshadri Vasudevan epp->first_ebr_is_null = 1; 234*bb9b6b3fSSheshadri Vasudevan epp->corrupt_logical_drives = 0; 235*bb9b6b3fSSheshadri Vasudevan epp->logical_drive_count = 0; 236*bb9b6b3fSSheshadri Vasudevan epp->invalid_bb_sig[0] = 0; 237*bb9b6b3fSSheshadri Vasudevan if (epp->op_flag & FDISK_READ_DISK) { 238*bb9b6b3fSSheshadri Vasudevan rval = fdisk_read_extpart(epp); 239*bb9b6b3fSSheshadri Vasudevan } 240*bb9b6b3fSSheshadri Vasudevan return (rval); 241*bb9b6b3fSSheshadri Vasudevan } 242*bb9b6b3fSSheshadri Vasudevan 243*bb9b6b3fSSheshadri Vasudevan void 244*bb9b6b3fSSheshadri Vasudevan libfdisk_fini(ext_part_t **epp) 245*bb9b6b3fSSheshadri Vasudevan { 246*bb9b6b3fSSheshadri Vasudevan fdisk_free_ld_nodes(*epp); 247*bb9b6b3fSSheshadri Vasudevan (void) close((*epp)->dev_fd); 248*bb9b6b3fSSheshadri Vasudevan free(*epp); 249*bb9b6b3fSSheshadri Vasudevan *epp = NULL; 250*bb9b6b3fSSheshadri Vasudevan } 251*bb9b6b3fSSheshadri Vasudevan 252*bb9b6b3fSSheshadri Vasudevan int 253*bb9b6b3fSSheshadri Vasudevan fdisk_is_linux_swap(ext_part_t *epp, uint32_t part_start, uint64_t *lsm_offset) 254*bb9b6b3fSSheshadri Vasudevan { 255*bb9b6b3fSSheshadri Vasudevan int i; 256*bb9b6b3fSSheshadri Vasudevan int rval = -1; 257*bb9b6b3fSSheshadri Vasudevan off_t seek_offset; 258*bb9b6b3fSSheshadri Vasudevan uint32_t linux_pg_size; 259*bb9b6b3fSSheshadri Vasudevan char *buf, *linux_swap_magic; 260*bb9b6b3fSSheshadri Vasudevan int sec_sz = fdisk_get_disk_geom(epp, PHYSGEOM, SSIZE); 261*bb9b6b3fSSheshadri Vasudevan off_t label_offset; 262*bb9b6b3fSSheshadri Vasudevan 263*bb9b6b3fSSheshadri Vasudevan /* 264*bb9b6b3fSSheshadri Vasudevan * Known linux kernel page sizes 265*bb9b6b3fSSheshadri Vasudevan * The linux swap magic is found as the last 10 bytes of a disk chunk 266*bb9b6b3fSSheshadri Vasudevan * at the beginning of the linux swap partition whose size is that of 267*bb9b6b3fSSheshadri Vasudevan * kernel page size. 268*bb9b6b3fSSheshadri Vasudevan */ 269*bb9b6b3fSSheshadri Vasudevan uint32_t linux_pg_size_arr[] = {4096, }; 270*bb9b6b3fSSheshadri Vasudevan 271*bb9b6b3fSSheshadri Vasudevan if ((buf = calloc(1, sec_sz)) == NULL) { 272*bb9b6b3fSSheshadri Vasudevan return (ENOMEM); 273*bb9b6b3fSSheshadri Vasudevan } 274*bb9b6b3fSSheshadri Vasudevan 275*bb9b6b3fSSheshadri Vasudevan /* 276*bb9b6b3fSSheshadri Vasudevan * Check if there is a sane Solaris VTOC 277*bb9b6b3fSSheshadri Vasudevan * If there is a valid vtoc, no need to lookup 278*bb9b6b3fSSheshadri Vasudevan * for the linux swap signature. 279*bb9b6b3fSSheshadri Vasudevan */ 280*bb9b6b3fSSheshadri Vasudevan label_offset = (part_start + DK_LABEL_LOC) * sec_sz; 281*bb9b6b3fSSheshadri Vasudevan if ((rval = lseek(epp->dev_fd, label_offset, SEEK_SET)) < 0) 282*bb9b6b3fSSheshadri Vasudevan goto done; 283*bb9b6b3fSSheshadri Vasudevan 284*bb9b6b3fSSheshadri Vasudevan if ((rval = read(epp->dev_fd, buf, sec_sz)) < sec_sz) { 285*bb9b6b3fSSheshadri Vasudevan rval = EIO; 286*bb9b6b3fSSheshadri Vasudevan goto done; 287*bb9b6b3fSSheshadri Vasudevan } 288*bb9b6b3fSSheshadri Vasudevan 289*bb9b6b3fSSheshadri Vasudevan 290*bb9b6b3fSSheshadri Vasudevan if ((((struct dk_label *)buf)->dkl_magic == DKL_MAGIC) && 291*bb9b6b3fSSheshadri Vasudevan (((struct dk_label *)buf)->dkl_vtoc.v_sanity == VTOC_SANE)) { 292*bb9b6b3fSSheshadri Vasudevan rval = -1; 293*bb9b6b3fSSheshadri Vasudevan goto done; 294*bb9b6b3fSSheshadri Vasudevan } 295*bb9b6b3fSSheshadri Vasudevan 296*bb9b6b3fSSheshadri Vasudevan /* No valid vtoc, so check for linux swap signature */ 297*bb9b6b3fSSheshadri Vasudevan linux_swap_magic = buf + sec_sz - LINUX_SWAP_MAGIC_LENGTH; 298*bb9b6b3fSSheshadri Vasudevan 299*bb9b6b3fSSheshadri Vasudevan for (i = 0; i < sizeof (linux_pg_size_arr)/sizeof (uint32_t); i++) { 300*bb9b6b3fSSheshadri Vasudevan linux_pg_size = linux_pg_size_arr[i]; 301*bb9b6b3fSSheshadri Vasudevan seek_offset = linux_pg_size/sec_sz - 1; 302*bb9b6b3fSSheshadri Vasudevan seek_offset += part_start; 303*bb9b6b3fSSheshadri Vasudevan seek_offset *= sec_sz; 304*bb9b6b3fSSheshadri Vasudevan 305*bb9b6b3fSSheshadri Vasudevan if ((rval = lseek(epp->dev_fd, seek_offset, SEEK_SET)) < 0) { 306*bb9b6b3fSSheshadri Vasudevan break; 307*bb9b6b3fSSheshadri Vasudevan } 308*bb9b6b3fSSheshadri Vasudevan 309*bb9b6b3fSSheshadri Vasudevan if ((rval = read(epp->dev_fd, buf, sec_sz)) < sec_sz) { 310*bb9b6b3fSSheshadri Vasudevan rval = EIO; 311*bb9b6b3fSSheshadri Vasudevan break; 312*bb9b6b3fSSheshadri Vasudevan } 313*bb9b6b3fSSheshadri Vasudevan 314*bb9b6b3fSSheshadri Vasudevan if ((strncmp(linux_swap_magic, "SWAP-SPACE", 315*bb9b6b3fSSheshadri Vasudevan LINUX_SWAP_MAGIC_LENGTH) == 0) || 316*bb9b6b3fSSheshadri Vasudevan (strncmp(linux_swap_magic, "SWAPSPACE2", 317*bb9b6b3fSSheshadri Vasudevan LINUX_SWAP_MAGIC_LENGTH) == 0)) { 318*bb9b6b3fSSheshadri Vasudevan /* Found a linux swap */ 319*bb9b6b3fSSheshadri Vasudevan rval = 0; 320*bb9b6b3fSSheshadri Vasudevan if (lsm_offset != NULL) 321*bb9b6b3fSSheshadri Vasudevan *lsm_offset = (uint64_t)seek_offset; 322*bb9b6b3fSSheshadri Vasudevan break; 323*bb9b6b3fSSheshadri Vasudevan } 324*bb9b6b3fSSheshadri Vasudevan } 325*bb9b6b3fSSheshadri Vasudevan 326*bb9b6b3fSSheshadri Vasudevan done: 327*bb9b6b3fSSheshadri Vasudevan free(buf); 328*bb9b6b3fSSheshadri Vasudevan return (rval); 329*bb9b6b3fSSheshadri Vasudevan } 330*bb9b6b3fSSheshadri Vasudevan 331*bb9b6b3fSSheshadri Vasudevan int 332*bb9b6b3fSSheshadri Vasudevan fdisk_get_solaris_part(ext_part_t *epp, int *pnum, uint32_t *begsec, 333*bb9b6b3fSSheshadri Vasudevan uint32_t *numsec) 334*bb9b6b3fSSheshadri Vasudevan { 335*bb9b6b3fSSheshadri Vasudevan logical_drive_t *temp = fdisk_get_ld_head(epp); 336*bb9b6b3fSSheshadri Vasudevan uint32_t part_start; 337*bb9b6b3fSSheshadri Vasudevan int pno; 338*bb9b6b3fSSheshadri Vasudevan int rval = -1; 339*bb9b6b3fSSheshadri Vasudevan 340*bb9b6b3fSSheshadri Vasudevan for (pno = 5; temp != NULL; temp = temp->next, pno++) { 341*bb9b6b3fSSheshadri Vasudevan if (fdisk_is_solaris_part(LE_8(temp->parts[0].systid))) { 342*bb9b6b3fSSheshadri Vasudevan part_start = temp->abs_secnum + temp->logdrive_offset; 343*bb9b6b3fSSheshadri Vasudevan if ((temp->parts[0].systid == SUNIXOS) && 344*bb9b6b3fSSheshadri Vasudevan (fdisk_is_linux_swap(epp, part_start, 345*bb9b6b3fSSheshadri Vasudevan NULL) == 0)) { 346*bb9b6b3fSSheshadri Vasudevan continue; 347*bb9b6b3fSSheshadri Vasudevan } 348*bb9b6b3fSSheshadri Vasudevan *pnum = pno; 349*bb9b6b3fSSheshadri Vasudevan *begsec = part_start; 350*bb9b6b3fSSheshadri Vasudevan *numsec = temp->numsect; 351*bb9b6b3fSSheshadri Vasudevan rval = FDISK_SUCCESS; 352*bb9b6b3fSSheshadri Vasudevan } 353*bb9b6b3fSSheshadri Vasudevan } 354*bb9b6b3fSSheshadri Vasudevan return (rval); 355*bb9b6b3fSSheshadri Vasudevan } 356*bb9b6b3fSSheshadri Vasudevan 357*bb9b6b3fSSheshadri Vasudevan int 358*bb9b6b3fSSheshadri Vasudevan fdisk_get_part_info(ext_part_t *epp, int pnum, uchar_t *sysid, uint32_t *begsec, 359*bb9b6b3fSSheshadri Vasudevan uint32_t *numsec) 360*bb9b6b3fSSheshadri Vasudevan { 361*bb9b6b3fSSheshadri Vasudevan logical_drive_t *temp = fdisk_get_ld_head(epp); 362*bb9b6b3fSSheshadri Vasudevan int pno; 363*bb9b6b3fSSheshadri Vasudevan 364*bb9b6b3fSSheshadri Vasudevan if ((pnum < 5) || (pnum >= MAX_EXT_PARTS + 5)) { 365*bb9b6b3fSSheshadri Vasudevan return (EINVAL); 366*bb9b6b3fSSheshadri Vasudevan } 367*bb9b6b3fSSheshadri Vasudevan 368*bb9b6b3fSSheshadri Vasudevan for (pno = 5; (pno < pnum) && (temp != NULL); temp = temp->next, pno++) 369*bb9b6b3fSSheshadri Vasudevan ; 370*bb9b6b3fSSheshadri Vasudevan 371*bb9b6b3fSSheshadri Vasudevan if (temp == NULL) { 372*bb9b6b3fSSheshadri Vasudevan return (EINVAL); 373*bb9b6b3fSSheshadri Vasudevan } 374*bb9b6b3fSSheshadri Vasudevan 375*bb9b6b3fSSheshadri Vasudevan *sysid = LE_8(temp->parts[0].systid); 376*bb9b6b3fSSheshadri Vasudevan *begsec = temp->abs_secnum + temp->logdrive_offset; 377*bb9b6b3fSSheshadri Vasudevan *numsec = temp->numsect; 378*bb9b6b3fSSheshadri Vasudevan return (FDISK_SUCCESS); 379*bb9b6b3fSSheshadri Vasudevan } 380*bb9b6b3fSSheshadri Vasudevan 381*bb9b6b3fSSheshadri Vasudevan /* 382*bb9b6b3fSSheshadri Vasudevan * Allocate a node of type logical_drive_t and return the pointer to it 383*bb9b6b3fSSheshadri Vasudevan */ 384*bb9b6b3fSSheshadri Vasudevan static logical_drive_t * 385*bb9b6b3fSSheshadri Vasudevan fdisk_alloc_ld_node() 386*bb9b6b3fSSheshadri Vasudevan { 387*bb9b6b3fSSheshadri Vasudevan logical_drive_t *temp; 388*bb9b6b3fSSheshadri Vasudevan 389*bb9b6b3fSSheshadri Vasudevan if ((temp = calloc(1, sizeof (logical_drive_t))) == NULL) { 390*bb9b6b3fSSheshadri Vasudevan return (NULL); 391*bb9b6b3fSSheshadri Vasudevan } 392*bb9b6b3fSSheshadri Vasudevan temp->next = NULL; 393*bb9b6b3fSSheshadri Vasudevan return (temp); 394*bb9b6b3fSSheshadri Vasudevan } 395*bb9b6b3fSSheshadri Vasudevan 396*bb9b6b3fSSheshadri Vasudevan /* 397*bb9b6b3fSSheshadri Vasudevan * Free all the logical_drive_t's allocated during the run 398*bb9b6b3fSSheshadri Vasudevan */ 399*bb9b6b3fSSheshadri Vasudevan static void 400*bb9b6b3fSSheshadri Vasudevan fdisk_free_ld_nodes(ext_part_t *epp) 401*bb9b6b3fSSheshadri Vasudevan { 402*bb9b6b3fSSheshadri Vasudevan logical_drive_t *temp; 403*bb9b6b3fSSheshadri Vasudevan 404*bb9b6b3fSSheshadri Vasudevan for (temp = epp->ld_head; temp != NULL; ) { 405*bb9b6b3fSSheshadri Vasudevan temp = epp->ld_head -> next; 406*bb9b6b3fSSheshadri Vasudevan free(epp->ld_head); 407*bb9b6b3fSSheshadri Vasudevan epp->ld_head = temp; 408*bb9b6b3fSSheshadri Vasudevan } 409*bb9b6b3fSSheshadri Vasudevan epp->ld_head = NULL; 410*bb9b6b3fSSheshadri Vasudevan epp->sorted_ld_head = NULL; 411*bb9b6b3fSSheshadri Vasudevan } 412*bb9b6b3fSSheshadri Vasudevan 413*bb9b6b3fSSheshadri Vasudevan /* 414*bb9b6b3fSSheshadri Vasudevan * Find the first free sector within the extended partition 415*bb9b6b3fSSheshadri Vasudevan */ 416*bb9b6b3fSSheshadri Vasudevan int 417*bb9b6b3fSSheshadri Vasudevan fdisk_ext_find_first_free_sec(ext_part_t *epp, uint32_t *first_free_sec) 418*bb9b6b3fSSheshadri Vasudevan { 419*bb9b6b3fSSheshadri Vasudevan logical_drive_t *temp; 420*bb9b6b3fSSheshadri Vasudevan uint32_t last_free_sec; 421*bb9b6b3fSSheshadri Vasudevan 422*bb9b6b3fSSheshadri Vasudevan *first_free_sec = epp->ext_beg_sec; 423*bb9b6b3fSSheshadri Vasudevan 424*bb9b6b3fSSheshadri Vasudevan if (epp->ld_head == NULL) { 425*bb9b6b3fSSheshadri Vasudevan return (FDISK_SUCCESS); 426*bb9b6b3fSSheshadri Vasudevan } 427*bb9b6b3fSSheshadri Vasudevan 428*bb9b6b3fSSheshadri Vasudevan /* 429*bb9b6b3fSSheshadri Vasudevan * When the first logical drive is out of order, we need to adjust 430*bb9b6b3fSSheshadri Vasudevan * first_free_sec accordingly. In this case, the first extended 431*bb9b6b3fSSheshadri Vasudevan * partition sector is not free even though the actual logical drive 432*bb9b6b3fSSheshadri Vasudevan * does not occupy space from the beginning of the extended partition. 433*bb9b6b3fSSheshadri Vasudevan * The next free sector would be the second sector of the extended 434*bb9b6b3fSSheshadri Vasudevan * partition. 435*bb9b6b3fSSheshadri Vasudevan */ 436*bb9b6b3fSSheshadri Vasudevan if (epp->ld_head->abs_secnum > epp->ext_beg_sec + 437*bb9b6b3fSSheshadri Vasudevan MAX_LOGDRIVE_OFFSET) { 438*bb9b6b3fSSheshadri Vasudevan (*first_free_sec)++; 439*bb9b6b3fSSheshadri Vasudevan } 440*bb9b6b3fSSheshadri Vasudevan 441*bb9b6b3fSSheshadri Vasudevan while (*first_free_sec <= epp->ext_end_sec) { 442*bb9b6b3fSSheshadri Vasudevan for (temp = epp->sorted_ld_head; temp != NULL; temp = 443*bb9b6b3fSSheshadri Vasudevan temp->sorted_next) { 444*bb9b6b3fSSheshadri Vasudevan if (temp->abs_secnum == *first_free_sec) { 445*bb9b6b3fSSheshadri Vasudevan *first_free_sec = temp->abs_secnum + 446*bb9b6b3fSSheshadri Vasudevan temp->logdrive_offset + temp->numsect; 447*bb9b6b3fSSheshadri Vasudevan } 448*bb9b6b3fSSheshadri Vasudevan } 449*bb9b6b3fSSheshadri Vasudevan 450*bb9b6b3fSSheshadri Vasudevan last_free_sec = fdisk_ext_find_last_free_sec(epp, 451*bb9b6b3fSSheshadri Vasudevan *first_free_sec); 452*bb9b6b3fSSheshadri Vasudevan 453*bb9b6b3fSSheshadri Vasudevan if ((last_free_sec - *first_free_sec) < MAX_LOGDRIVE_OFFSET) { 454*bb9b6b3fSSheshadri Vasudevan /* 455*bb9b6b3fSSheshadri Vasudevan * Minimum size of a partition assumed to be atleast one 456*bb9b6b3fSSheshadri Vasudevan * sector. 457*bb9b6b3fSSheshadri Vasudevan */ 458*bb9b6b3fSSheshadri Vasudevan *first_free_sec = last_free_sec + 1; 459*bb9b6b3fSSheshadri Vasudevan continue; 460*bb9b6b3fSSheshadri Vasudevan } 461*bb9b6b3fSSheshadri Vasudevan 462*bb9b6b3fSSheshadri Vasudevan break; 463*bb9b6b3fSSheshadri Vasudevan } 464*bb9b6b3fSSheshadri Vasudevan 465*bb9b6b3fSSheshadri Vasudevan if (*first_free_sec > epp->ext_end_sec) { 466*bb9b6b3fSSheshadri Vasudevan return (FDISK_EOOBOUND); 467*bb9b6b3fSSheshadri Vasudevan } 468*bb9b6b3fSSheshadri Vasudevan 469*bb9b6b3fSSheshadri Vasudevan return (FDISK_SUCCESS); 470*bb9b6b3fSSheshadri Vasudevan } 471*bb9b6b3fSSheshadri Vasudevan 472*bb9b6b3fSSheshadri Vasudevan /* 473*bb9b6b3fSSheshadri Vasudevan * Find the last free sector within the extended partition given, a beginning 474*bb9b6b3fSSheshadri Vasudevan * sector (so that the range - "begsec to last_free_sec" is contiguous) 475*bb9b6b3fSSheshadri Vasudevan */ 476*bb9b6b3fSSheshadri Vasudevan uint32_t 477*bb9b6b3fSSheshadri Vasudevan fdisk_ext_find_last_free_sec(ext_part_t *epp, uint32_t begsec) 478*bb9b6b3fSSheshadri Vasudevan { 479*bb9b6b3fSSheshadri Vasudevan logical_drive_t *temp; 480*bb9b6b3fSSheshadri Vasudevan uint32_t last_free_sec; 481*bb9b6b3fSSheshadri Vasudevan 482*bb9b6b3fSSheshadri Vasudevan last_free_sec = epp->ext_end_sec; 483*bb9b6b3fSSheshadri Vasudevan for (temp = epp->sorted_ld_head; temp != NULL; 484*bb9b6b3fSSheshadri Vasudevan temp = temp->sorted_next) { 485*bb9b6b3fSSheshadri Vasudevan if (temp->abs_secnum > begsec) { 486*bb9b6b3fSSheshadri Vasudevan last_free_sec = temp->abs_secnum - 1; 487*bb9b6b3fSSheshadri Vasudevan break; 488*bb9b6b3fSSheshadri Vasudevan } 489*bb9b6b3fSSheshadri Vasudevan } 490*bb9b6b3fSSheshadri Vasudevan return (last_free_sec); 491*bb9b6b3fSSheshadri Vasudevan } 492*bb9b6b3fSSheshadri Vasudevan 493*bb9b6b3fSSheshadri Vasudevan /* 494*bb9b6b3fSSheshadri Vasudevan * Place the given ext_part_t structure in a sorted list, sorted in the 495*bb9b6b3fSSheshadri Vasudevan * ascending order of their beginning sectors. 496*bb9b6b3fSSheshadri Vasudevan */ 497*bb9b6b3fSSheshadri Vasudevan static void 498*bb9b6b3fSSheshadri Vasudevan fdisk_ext_place_in_sorted_list(ext_part_t *epp, logical_drive_t *newld) 499*bb9b6b3fSSheshadri Vasudevan { 500*bb9b6b3fSSheshadri Vasudevan logical_drive_t *pre, *cur; 501*bb9b6b3fSSheshadri Vasudevan 502*bb9b6b3fSSheshadri Vasudevan if (newld->abs_secnum < epp->sorted_ld_head->abs_secnum) { 503*bb9b6b3fSSheshadri Vasudevan newld->sorted_next = epp->sorted_ld_head; 504*bb9b6b3fSSheshadri Vasudevan epp->sorted_ld_head = newld; 505*bb9b6b3fSSheshadri Vasudevan return; 506*bb9b6b3fSSheshadri Vasudevan } 507*bb9b6b3fSSheshadri Vasudevan pre = cur = epp->sorted_ld_head; 508*bb9b6b3fSSheshadri Vasudevan 509*bb9b6b3fSSheshadri Vasudevan for (; cur != NULL; pre = cur, cur = cur->sorted_next) { 510*bb9b6b3fSSheshadri Vasudevan if (newld->abs_secnum < cur->abs_secnum) { 511*bb9b6b3fSSheshadri Vasudevan break; 512*bb9b6b3fSSheshadri Vasudevan } 513*bb9b6b3fSSheshadri Vasudevan } 514*bb9b6b3fSSheshadri Vasudevan 515*bb9b6b3fSSheshadri Vasudevan newld->sorted_next = cur; 516*bb9b6b3fSSheshadri Vasudevan pre->sorted_next = newld; 517*bb9b6b3fSSheshadri Vasudevan } 518*bb9b6b3fSSheshadri Vasudevan 519*bb9b6b3fSSheshadri Vasudevan static void 520*bb9b6b3fSSheshadri Vasudevan fdisk_ext_remove_from_sorted_list(ext_part_t *epp, logical_drive_t *delld) 521*bb9b6b3fSSheshadri Vasudevan { 522*bb9b6b3fSSheshadri Vasudevan logical_drive_t *pre, *cur; 523*bb9b6b3fSSheshadri Vasudevan 524*bb9b6b3fSSheshadri Vasudevan if (delld == epp->sorted_ld_head) { 525*bb9b6b3fSSheshadri Vasudevan epp->sorted_ld_head = delld->sorted_next; 526*bb9b6b3fSSheshadri Vasudevan return; 527*bb9b6b3fSSheshadri Vasudevan } 528*bb9b6b3fSSheshadri Vasudevan 529*bb9b6b3fSSheshadri Vasudevan pre = cur = epp->sorted_ld_head; 530*bb9b6b3fSSheshadri Vasudevan 531*bb9b6b3fSSheshadri Vasudevan for (; cur != NULL; pre = cur, cur = cur->sorted_next) { 532*bb9b6b3fSSheshadri Vasudevan if (cur->abs_secnum == delld->abs_secnum) { 533*bb9b6b3fSSheshadri Vasudevan /* Found */ 534*bb9b6b3fSSheshadri Vasudevan break; 535*bb9b6b3fSSheshadri Vasudevan } 536*bb9b6b3fSSheshadri Vasudevan } 537*bb9b6b3fSSheshadri Vasudevan 538*bb9b6b3fSSheshadri Vasudevan pre->sorted_next = cur->sorted_next; 539*bb9b6b3fSSheshadri Vasudevan } 540*bb9b6b3fSSheshadri Vasudevan 541*bb9b6b3fSSheshadri Vasudevan static int 542*bb9b6b3fSSheshadri Vasudevan fdisk_ext_overlapping_parts(ext_part_t *epp, uint32_t begsec, uint32_t endsec) 543*bb9b6b3fSSheshadri Vasudevan { 544*bb9b6b3fSSheshadri Vasudevan logical_drive_t *temp; 545*bb9b6b3fSSheshadri Vasudevan uint32_t firstsec, lastsec, last_free_sec; 546*bb9b6b3fSSheshadri Vasudevan 547*bb9b6b3fSSheshadri Vasudevan for (temp = epp->ld_head; temp != NULL; temp = temp->next) { 548*bb9b6b3fSSheshadri Vasudevan firstsec = temp->abs_secnum; 549*bb9b6b3fSSheshadri Vasudevan lastsec = firstsec + temp->logdrive_offset + temp->numsect - 1; 550*bb9b6b3fSSheshadri Vasudevan if ((begsec >= firstsec) && 551*bb9b6b3fSSheshadri Vasudevan (begsec <= lastsec)) { 552*bb9b6b3fSSheshadri Vasudevan return (1); 553*bb9b6b3fSSheshadri Vasudevan } 554*bb9b6b3fSSheshadri Vasudevan } 555*bb9b6b3fSSheshadri Vasudevan 556*bb9b6b3fSSheshadri Vasudevan /* 557*bb9b6b3fSSheshadri Vasudevan * Find the maximum possible end sector value 558*bb9b6b3fSSheshadri Vasudevan * given a beginning sector value 559*bb9b6b3fSSheshadri Vasudevan */ 560*bb9b6b3fSSheshadri Vasudevan last_free_sec = fdisk_ext_find_last_free_sec(epp, begsec); 561*bb9b6b3fSSheshadri Vasudevan 562*bb9b6b3fSSheshadri Vasudevan if (endsec > last_free_sec) { 563*bb9b6b3fSSheshadri Vasudevan return (1); 564*bb9b6b3fSSheshadri Vasudevan } 565*bb9b6b3fSSheshadri Vasudevan return (0); 566*bb9b6b3fSSheshadri Vasudevan } 567*bb9b6b3fSSheshadri Vasudevan 568*bb9b6b3fSSheshadri Vasudevan /* 569*bb9b6b3fSSheshadri Vasudevan * Check if the logical drive boundaries are sane 570*bb9b6b3fSSheshadri Vasudevan */ 571*bb9b6b3fSSheshadri Vasudevan int 572*bb9b6b3fSSheshadri Vasudevan fdisk_validate_logical_drive(ext_part_t *epp, uint32_t begsec, 573*bb9b6b3fSSheshadri Vasudevan uint32_t offset, uint32_t numsec) 574*bb9b6b3fSSheshadri Vasudevan { 575*bb9b6b3fSSheshadri Vasudevan uint32_t endsec; 576*bb9b6b3fSSheshadri Vasudevan 577*bb9b6b3fSSheshadri Vasudevan endsec = begsec + offset + numsec - 1; 578*bb9b6b3fSSheshadri Vasudevan if (begsec < epp->ext_beg_sec || 579*bb9b6b3fSSheshadri Vasudevan begsec > epp->ext_end_sec || 580*bb9b6b3fSSheshadri Vasudevan endsec < epp->ext_beg_sec || 581*bb9b6b3fSSheshadri Vasudevan endsec > epp->ext_end_sec || 582*bb9b6b3fSSheshadri Vasudevan endsec < begsec || 583*bb9b6b3fSSheshadri Vasudevan fdisk_ext_overlapping_parts(epp, begsec, endsec)) { 584*bb9b6b3fSSheshadri Vasudevan return (1); 585*bb9b6b3fSSheshadri Vasudevan } 586*bb9b6b3fSSheshadri Vasudevan 587*bb9b6b3fSSheshadri Vasudevan return (0); 588*bb9b6b3fSSheshadri Vasudevan } 589*bb9b6b3fSSheshadri Vasudevan 590*bb9b6b3fSSheshadri Vasudevan /* 591*bb9b6b3fSSheshadri Vasudevan * Procedure to walk through the extended partitions and build a Singly 592*bb9b6b3fSSheshadri Vasudevan * Linked List out of the data. 593*bb9b6b3fSSheshadri Vasudevan */ 594*bb9b6b3fSSheshadri Vasudevan int 595*bb9b6b3fSSheshadri Vasudevan fdisk_read_extpart(ext_part_t *epp) 596*bb9b6b3fSSheshadri Vasudevan { 597*bb9b6b3fSSheshadri Vasudevan struct ipart *fdp, *ext_fdp; 598*bb9b6b3fSSheshadri Vasudevan int i = 0, j = 0, ext_part_found = 0, lpart = 5; 599*bb9b6b3fSSheshadri Vasudevan off_t secnum, offset; 600*bb9b6b3fSSheshadri Vasudevan logical_drive_t *temp, *ep_ptr; 601*bb9b6b3fSSheshadri Vasudevan unsigned char *ext_buf; 602*bb9b6b3fSSheshadri Vasudevan int sectsize = epp->disk_geom.sectsize; 603*bb9b6b3fSSheshadri Vasudevan 604*bb9b6b3fSSheshadri Vasudevan if ((ext_buf = (uchar_t *)malloc(sectsize)) == NULL) { 605*bb9b6b3fSSheshadri Vasudevan return (ENOMEM); 606*bb9b6b3fSSheshadri Vasudevan } 607*bb9b6b3fSSheshadri Vasudevan fdp = epp->mtable; 608*bb9b6b3fSSheshadri Vasudevan 609*bb9b6b3fSSheshadri Vasudevan for (i = 0; (i < FD_NUMPART) && (!ext_part_found); i++, fdp++) { 610*bb9b6b3fSSheshadri Vasudevan if (fdisk_is_dos_extended(LE_8(fdp->systid))) { 611*bb9b6b3fSSheshadri Vasudevan ext_part_found = 1; 612*bb9b6b3fSSheshadri Vasudevan secnum = LE_32(fdp->relsect); 613*bb9b6b3fSSheshadri Vasudevan offset = secnum * sectsize; 614*bb9b6b3fSSheshadri Vasudevan epp->ext_beg_sec = secnum; 615*bb9b6b3fSSheshadri Vasudevan epp->ext_end_sec = secnum + LE_32(fdp->numsect) - 1; 616*bb9b6b3fSSheshadri Vasudevan epp->ext_beg_cyl = 617*bb9b6b3fSSheshadri Vasudevan FDISK_SECT_TO_CYL(epp, epp->ext_beg_sec); 618*bb9b6b3fSSheshadri Vasudevan epp->ext_end_cyl = 619*bb9b6b3fSSheshadri Vasudevan FDISK_SECT_TO_CYL(epp, epp->ext_end_sec); 620*bb9b6b3fSSheshadri Vasudevan 621*bb9b6b3fSSheshadri Vasudevan /*LINTED*/ 622*bb9b6b3fSSheshadri Vasudevan while (B_TRUE) { 623*bb9b6b3fSSheshadri Vasudevan if (lseek(epp->dev_fd, offset, SEEK_SET) < 0) { 624*bb9b6b3fSSheshadri Vasudevan return (EIO); 625*bb9b6b3fSSheshadri Vasudevan } 626*bb9b6b3fSSheshadri Vasudevan if (read(epp->dev_fd, ext_buf, sectsize) < 627*bb9b6b3fSSheshadri Vasudevan sectsize) { 628*bb9b6b3fSSheshadri Vasudevan return (EIO); 629*bb9b6b3fSSheshadri Vasudevan } 630*bb9b6b3fSSheshadri Vasudevan /*LINTED*/ 631*bb9b6b3fSSheshadri Vasudevan ext_fdp = (struct ipart *) 632*bb9b6b3fSSheshadri Vasudevan (&ext_buf[FDISK_PART_TABLE_START]); 633*bb9b6b3fSSheshadri Vasudevan if ((LE_32(ext_fdp->relsect) == 0) && 634*bb9b6b3fSSheshadri Vasudevan (epp->logical_drive_count == 0)) { 635*bb9b6b3fSSheshadri Vasudevan /* No logical drives defined */ 636*bb9b6b3fSSheshadri Vasudevan epp->first_ebr_is_null = 0; 637*bb9b6b3fSSheshadri Vasudevan return (FDISK_ENOLOGDRIVE); 638*bb9b6b3fSSheshadri Vasudevan } 639*bb9b6b3fSSheshadri Vasudevan 640*bb9b6b3fSSheshadri Vasudevan temp = fdisk_alloc_ld_node(); 641*bb9b6b3fSSheshadri Vasudevan temp->abs_secnum = secnum; 642*bb9b6b3fSSheshadri Vasudevan temp->logdrive_offset = 643*bb9b6b3fSSheshadri Vasudevan LE_32(ext_fdp->relsect); 644*bb9b6b3fSSheshadri Vasudevan temp ->numsect = LE_32(ext_fdp->numsect); 645*bb9b6b3fSSheshadri Vasudevan if (epp->ld_head == NULL) { 646*bb9b6b3fSSheshadri Vasudevan /* adding first logical drive */ 647*bb9b6b3fSSheshadri Vasudevan if (temp->logdrive_offset > 648*bb9b6b3fSSheshadri Vasudevan MAX_LOGDRIVE_OFFSET) { 649*bb9b6b3fSSheshadri Vasudevan /* out of order */ 650*bb9b6b3fSSheshadri Vasudevan temp->abs_secnum += 651*bb9b6b3fSSheshadri Vasudevan temp->logdrive_offset; 652*bb9b6b3fSSheshadri Vasudevan temp->logdrive_offset = 0; 653*bb9b6b3fSSheshadri Vasudevan } 654*bb9b6b3fSSheshadri Vasudevan } 655*bb9b6b3fSSheshadri Vasudevan temp->begcyl = 656*bb9b6b3fSSheshadri Vasudevan FDISK_SECT_TO_CYL(epp, temp->abs_secnum); 657*bb9b6b3fSSheshadri Vasudevan temp->endcyl = FDISK_SECT_TO_CYL(epp, 658*bb9b6b3fSSheshadri Vasudevan temp->abs_secnum + 659*bb9b6b3fSSheshadri Vasudevan temp->logdrive_offset + 660*bb9b6b3fSSheshadri Vasudevan temp->numsect - 1); 661*bb9b6b3fSSheshadri Vasudevan 662*bb9b6b3fSSheshadri Vasudevan /* 663*bb9b6b3fSSheshadri Vasudevan * Check for sanity of logical drives 664*bb9b6b3fSSheshadri Vasudevan */ 665*bb9b6b3fSSheshadri Vasudevan if (fdisk_validate_logical_drive(epp, 666*bb9b6b3fSSheshadri Vasudevan temp->abs_secnum, temp->logdrive_offset, 667*bb9b6b3fSSheshadri Vasudevan temp->numsect)) { 668*bb9b6b3fSSheshadri Vasudevan epp->corrupt_logical_drives = 1; 669*bb9b6b3fSSheshadri Vasudevan free(temp); 670*bb9b6b3fSSheshadri Vasudevan return (FDISK_EBADLOGDRIVE); 671*bb9b6b3fSSheshadri Vasudevan } 672*bb9b6b3fSSheshadri Vasudevan 673*bb9b6b3fSSheshadri Vasudevan temp->parts[0] = *ext_fdp; 674*bb9b6b3fSSheshadri Vasudevan ext_fdp++; 675*bb9b6b3fSSheshadri Vasudevan temp->parts[1] = *ext_fdp; 676*bb9b6b3fSSheshadri Vasudevan 677*bb9b6b3fSSheshadri Vasudevan if (epp->ld_head == NULL) { 678*bb9b6b3fSSheshadri Vasudevan epp->ld_head = temp; 679*bb9b6b3fSSheshadri Vasudevan epp->sorted_ld_head = temp; 680*bb9b6b3fSSheshadri Vasudevan ep_ptr = temp; 681*bb9b6b3fSSheshadri Vasudevan epp->logical_drive_count = 1; 682*bb9b6b3fSSheshadri Vasudevan } else { 683*bb9b6b3fSSheshadri Vasudevan ep_ptr->next = temp; 684*bb9b6b3fSSheshadri Vasudevan ep_ptr = temp; 685*bb9b6b3fSSheshadri Vasudevan fdisk_ext_place_in_sorted_list(epp, 686*bb9b6b3fSSheshadri Vasudevan temp); 687*bb9b6b3fSSheshadri Vasudevan epp->logical_drive_count++; 688*bb9b6b3fSSheshadri Vasudevan } 689*bb9b6b3fSSheshadri Vasudevan 690*bb9b6b3fSSheshadri Vasudevan /*LINTED*/ 691*bb9b6b3fSSheshadri Vasudevan if (LE_16((*(uint16_t *)&ext_buf[510])) != 692*bb9b6b3fSSheshadri Vasudevan MBB_MAGIC) { 693*bb9b6b3fSSheshadri Vasudevan epp->invalid_bb_sig[j++] = lpart; 694*bb9b6b3fSSheshadri Vasudevan temp->modified = FDISK_MINOR_WRITE; 695*bb9b6b3fSSheshadri Vasudevan } 696*bb9b6b3fSSheshadri Vasudevan 697*bb9b6b3fSSheshadri Vasudevan if (LE_32(ext_fdp->relsect) == 0) 698*bb9b6b3fSSheshadri Vasudevan break; 699*bb9b6b3fSSheshadri Vasudevan else { 700*bb9b6b3fSSheshadri Vasudevan secnum = LE_32(fdp->relsect) + 701*bb9b6b3fSSheshadri Vasudevan LE_32(ext_fdp->relsect); 702*bb9b6b3fSSheshadri Vasudevan offset = secnum * sectsize; 703*bb9b6b3fSSheshadri Vasudevan } 704*bb9b6b3fSSheshadri Vasudevan lpart++; 705*bb9b6b3fSSheshadri Vasudevan } 706*bb9b6b3fSSheshadri Vasudevan } 707*bb9b6b3fSSheshadri Vasudevan } 708*bb9b6b3fSSheshadri Vasudevan return (FDISK_SUCCESS); 709*bb9b6b3fSSheshadri Vasudevan } 710*bb9b6b3fSSheshadri Vasudevan 711*bb9b6b3fSSheshadri Vasudevan static int 712*bb9b6b3fSSheshadri Vasudevan fdisk_init_master_part_table(ext_part_t *epp) 713*bb9b6b3fSSheshadri Vasudevan { 714*bb9b6b3fSSheshadri Vasudevan int rval; 715*bb9b6b3fSSheshadri Vasudevan if ((epp->mtable = fdisk_alloc_part_table()) == NULL) { 716*bb9b6b3fSSheshadri Vasudevan return (ENOMEM); 717*bb9b6b3fSSheshadri Vasudevan } 718*bb9b6b3fSSheshadri Vasudevan rval = fdisk_read_master_part_table(epp); 719*bb9b6b3fSSheshadri Vasudevan if (rval) { 720*bb9b6b3fSSheshadri Vasudevan return (rval); 721*bb9b6b3fSSheshadri Vasudevan } 722*bb9b6b3fSSheshadri Vasudevan return (FDISK_SUCCESS); 723*bb9b6b3fSSheshadri Vasudevan } 724*bb9b6b3fSSheshadri Vasudevan 725*bb9b6b3fSSheshadri Vasudevan static struct ipart * 726*bb9b6b3fSSheshadri Vasudevan fdisk_alloc_part_table() 727*bb9b6b3fSSheshadri Vasudevan { 728*bb9b6b3fSSheshadri Vasudevan int size = sizeof (struct ipart); 729*bb9b6b3fSSheshadri Vasudevan struct ipart *table; 730*bb9b6b3fSSheshadri Vasudevan 731*bb9b6b3fSSheshadri Vasudevan if ((table = calloc(4, size)) == NULL) { 732*bb9b6b3fSSheshadri Vasudevan return (NULL); 733*bb9b6b3fSSheshadri Vasudevan } 734*bb9b6b3fSSheshadri Vasudevan 735*bb9b6b3fSSheshadri Vasudevan return (table); 736*bb9b6b3fSSheshadri Vasudevan } 737*bb9b6b3fSSheshadri Vasudevan 738*bb9b6b3fSSheshadri Vasudevan /* 739*bb9b6b3fSSheshadri Vasudevan * Reads the master fdisk partition table from the device assuming that it has 740*bb9b6b3fSSheshadri Vasudevan * a valid table. 741*bb9b6b3fSSheshadri Vasudevan * MBR is supposed to be of 512 bytes no matter what the device block size is. 742*bb9b6b3fSSheshadri Vasudevan */ 743*bb9b6b3fSSheshadri Vasudevan static int 744*bb9b6b3fSSheshadri Vasudevan fdisk_read_master_part_table(ext_part_t *epp) 745*bb9b6b3fSSheshadri Vasudevan { 746*bb9b6b3fSSheshadri Vasudevan uchar_t buf[512]; 747*bb9b6b3fSSheshadri Vasudevan int sectsize = 512; 748*bb9b6b3fSSheshadri Vasudevan int size = sizeof (struct ipart); 749*bb9b6b3fSSheshadri Vasudevan int cpcnt = FD_NUMPART * size; 750*bb9b6b3fSSheshadri Vasudevan 751*bb9b6b3fSSheshadri Vasudevan if (lseek(epp->dev_fd, 0, SEEK_SET) < 0) { 752*bb9b6b3fSSheshadri Vasudevan return (EIO); 753*bb9b6b3fSSheshadri Vasudevan } 754*bb9b6b3fSSheshadri Vasudevan if (read(epp->dev_fd, buf, sectsize) < sectsize) { 755*bb9b6b3fSSheshadri Vasudevan return (EIO); 756*bb9b6b3fSSheshadri Vasudevan } 757*bb9b6b3fSSheshadri Vasudevan bcopy(&buf[FDISK_PART_TABLE_START], epp->mtable, cpcnt); 758*bb9b6b3fSSheshadri Vasudevan 759*bb9b6b3fSSheshadri Vasudevan /*LINTED*/ 760*bb9b6b3fSSheshadri Vasudevan if (LE_16((*(uint16_t *)&buf[510])) != MBB_MAGIC) { 761*bb9b6b3fSSheshadri Vasudevan return (FDISK_EBADMAGIC); 762*bb9b6b3fSSheshadri Vasudevan } 763*bb9b6b3fSSheshadri Vasudevan 764*bb9b6b3fSSheshadri Vasudevan return (FDISK_SUCCESS); 765*bb9b6b3fSSheshadri Vasudevan } 766*bb9b6b3fSSheshadri Vasudevan 767*bb9b6b3fSSheshadri Vasudevan int 768*bb9b6b3fSSheshadri Vasudevan fdisk_ext_part_exists(ext_part_t *epp) 769*bb9b6b3fSSheshadri Vasudevan { 770*bb9b6b3fSSheshadri Vasudevan int i; 771*bb9b6b3fSSheshadri Vasudevan struct ipart *part_table = epp->mtable; 772*bb9b6b3fSSheshadri Vasudevan 773*bb9b6b3fSSheshadri Vasudevan if (part_table == NULL) { 774*bb9b6b3fSSheshadri Vasudevan /* No extended partition found */ 775*bb9b6b3fSSheshadri Vasudevan return (0); 776*bb9b6b3fSSheshadri Vasudevan } 777*bb9b6b3fSSheshadri Vasudevan 778*bb9b6b3fSSheshadri Vasudevan for (i = 0; i < FD_NUMPART; i++) { 779*bb9b6b3fSSheshadri Vasudevan if (fdisk_is_dos_extended(LE_8(part_table[i].systid))) { 780*bb9b6b3fSSheshadri Vasudevan break; 781*bb9b6b3fSSheshadri Vasudevan } 782*bb9b6b3fSSheshadri Vasudevan } 783*bb9b6b3fSSheshadri Vasudevan 784*bb9b6b3fSSheshadri Vasudevan if (i == FD_NUMPART) { 785*bb9b6b3fSSheshadri Vasudevan /* No extended partition found */ 786*bb9b6b3fSSheshadri Vasudevan return (0); 787*bb9b6b3fSSheshadri Vasudevan } 788*bb9b6b3fSSheshadri Vasudevan return (1); 789*bb9b6b3fSSheshadri Vasudevan } 790*bb9b6b3fSSheshadri Vasudevan 791*bb9b6b3fSSheshadri Vasudevan int 792*bb9b6b3fSSheshadri Vasudevan fdisk_ext_validate_part_start(ext_part_t *epp, uint32_t begcyl, 793*bb9b6b3fSSheshadri Vasudevan uint32_t *begsec) 794*bb9b6b3fSSheshadri Vasudevan { 795*bb9b6b3fSSheshadri Vasudevan logical_drive_t *temp; 796*bb9b6b3fSSheshadri Vasudevan uint32_t first_free_sec; 797*bb9b6b3fSSheshadri Vasudevan uint32_t first_free_cyl; 798*bb9b6b3fSSheshadri Vasudevan int rval; 799*bb9b6b3fSSheshadri Vasudevan 800*bb9b6b3fSSheshadri Vasudevan rval = fdisk_ext_find_first_free_sec(epp, &first_free_sec); 801*bb9b6b3fSSheshadri Vasudevan if (rval != FDISK_SUCCESS) { 802*bb9b6b3fSSheshadri Vasudevan return (rval); 803*bb9b6b3fSSheshadri Vasudevan } 804*bb9b6b3fSSheshadri Vasudevan 805*bb9b6b3fSSheshadri Vasudevan first_free_cyl = FDISK_SECT_TO_CYL(epp, first_free_sec); 806*bb9b6b3fSSheshadri Vasudevan if (begcyl == first_free_cyl) { 807*bb9b6b3fSSheshadri Vasudevan *begsec = first_free_sec; 808*bb9b6b3fSSheshadri Vasudevan return (FDISK_SUCCESS); 809*bb9b6b3fSSheshadri Vasudevan } 810*bb9b6b3fSSheshadri Vasudevan 811*bb9b6b3fSSheshadri Vasudevan /* Check if the cylinder number is beyond the extended partition */ 812*bb9b6b3fSSheshadri Vasudevan if ((begcyl < epp->ext_beg_cyl) || (begcyl > epp->ext_end_cyl)) { 813*bb9b6b3fSSheshadri Vasudevan return (FDISK_EOOBOUND); 814*bb9b6b3fSSheshadri Vasudevan } 815*bb9b6b3fSSheshadri Vasudevan 816*bb9b6b3fSSheshadri Vasudevan for (temp = epp->ld_head; temp != NULL; temp = temp->next) { 817*bb9b6b3fSSheshadri Vasudevan if ((begcyl >= temp->begcyl) && 818*bb9b6b3fSSheshadri Vasudevan (begcyl <= temp->endcyl)) { 819*bb9b6b3fSSheshadri Vasudevan return (FDISK_EOVERLAP); 820*bb9b6b3fSSheshadri Vasudevan } 821*bb9b6b3fSSheshadri Vasudevan } 822*bb9b6b3fSSheshadri Vasudevan *begsec = FDISK_CYL_TO_SECT(epp, begcyl); 823*bb9b6b3fSSheshadri Vasudevan 824*bb9b6b3fSSheshadri Vasudevan return (FDISK_SUCCESS); 825*bb9b6b3fSSheshadri Vasudevan } 826*bb9b6b3fSSheshadri Vasudevan 827*bb9b6b3fSSheshadri Vasudevan void 828*bb9b6b3fSSheshadri Vasudevan fdisk_change_logical_drive_id(ext_part_t *epp, int pno, uchar_t partid) 829*bb9b6b3fSSheshadri Vasudevan { 830*bb9b6b3fSSheshadri Vasudevan logical_drive_t *temp; 831*bb9b6b3fSSheshadri Vasudevan int i; 832*bb9b6b3fSSheshadri Vasudevan 833*bb9b6b3fSSheshadri Vasudevan i = FD_NUMPART + 1; 834*bb9b6b3fSSheshadri Vasudevan for (temp = epp->ld_head; i < pno; temp = temp->next, i++) 835*bb9b6b3fSSheshadri Vasudevan ; 836*bb9b6b3fSSheshadri Vasudevan 837*bb9b6b3fSSheshadri Vasudevan temp->parts[0].systid = LE_8(partid); 838*bb9b6b3fSSheshadri Vasudevan temp->modified = FDISK_MAJOR_WRITE; 839*bb9b6b3fSSheshadri Vasudevan } 840*bb9b6b3fSSheshadri Vasudevan 841*bb9b6b3fSSheshadri Vasudevan /* 842*bb9b6b3fSSheshadri Vasudevan * A couple of special scenarios : 843*bb9b6b3fSSheshadri Vasudevan * 1. Since the first logical drive's EBR is always at the beginning of the 844*bb9b6b3fSSheshadri Vasudevan * extended partition, any specification that starts the first logical drive 845*bb9b6b3fSSheshadri Vasudevan * out of order will need to address the following issue : 846*bb9b6b3fSSheshadri Vasudevan * If the beginning of the drive is not coinciding with the beginning of the 847*bb9b6b3fSSheshadri Vasudevan * extended partition and : 848*bb9b6b3fSSheshadri Vasudevan * a) The start is within MAX_LOGDRIVE_OFFSET, the offset changes from the 849*bb9b6b3fSSheshadri Vasudevan * default of 63 to less than 63. 850*bb9b6b3fSSheshadri Vasudevan * logdrive_offset is updated to keep track of the space between 851*bb9b6b3fSSheshadri Vasudevan * the beginning of the logical drive and extended partition. abs_secnum 852*bb9b6b3fSSheshadri Vasudevan * points to the beginning of the extended partition. 853*bb9b6b3fSSheshadri Vasudevan * b) The start is greater than MAX_LOGDRIVE_OFFSET, the offset changes from 854*bb9b6b3fSSheshadri Vasudevan * the default of 63 to greater than 63. 855*bb9b6b3fSSheshadri Vasudevan * logdrive_offset is set to 0. abs_secnum points to the beginning of the 856*bb9b6b3fSSheshadri Vasudevan * logical drive, which is at an offset from the extended partition. 857*bb9b6b3fSSheshadri Vasudevan */ 858*bb9b6b3fSSheshadri Vasudevan void 859*bb9b6b3fSSheshadri Vasudevan fdisk_add_logical_drive(ext_part_t *epp, uint32_t begsec, uint32_t endsec, 860*bb9b6b3fSSheshadri Vasudevan uchar_t partid) 861*bb9b6b3fSSheshadri Vasudevan { 862*bb9b6b3fSSheshadri Vasudevan logical_drive_t *temp, *pre, *cur; 863*bb9b6b3fSSheshadri Vasudevan struct ipart *part; 864*bb9b6b3fSSheshadri Vasudevan 865*bb9b6b3fSSheshadri Vasudevan temp = fdisk_alloc_ld_node(); 866*bb9b6b3fSSheshadri Vasudevan temp->abs_secnum = begsec; 867*bb9b6b3fSSheshadri Vasudevan temp->logdrive_offset = MAX_LOGDRIVE_OFFSET; 868*bb9b6b3fSSheshadri Vasudevan temp->numsect = endsec - begsec + 1 - MAX_LOGDRIVE_OFFSET; 869*bb9b6b3fSSheshadri Vasudevan temp->begcyl = FDISK_SECT_TO_CYL(epp, begsec); 870*bb9b6b3fSSheshadri Vasudevan temp->endcyl = FDISK_SECT_TO_CYL(epp, endsec); 871*bb9b6b3fSSheshadri Vasudevan temp->modified = FDISK_MAJOR_WRITE; 872*bb9b6b3fSSheshadri Vasudevan 873*bb9b6b3fSSheshadri Vasudevan part = &temp->parts[0]; 874*bb9b6b3fSSheshadri Vasudevan part->bootid = 0; 875*bb9b6b3fSSheshadri Vasudevan part->systid = LE_8(partid); 876*bb9b6b3fSSheshadri Vasudevan part->relsect = MAX_LOGDRIVE_OFFSET; 877*bb9b6b3fSSheshadri Vasudevan part->numsect = LE_32(temp->numsect); 878*bb9b6b3fSSheshadri Vasudevan 879*bb9b6b3fSSheshadri Vasudevan fdisk_set_CHS_values(epp, part); 880*bb9b6b3fSSheshadri Vasudevan 881*bb9b6b3fSSheshadri Vasudevan if (epp->ld_head == NULL) { 882*bb9b6b3fSSheshadri Vasudevan epp->corrupt_logical_drives = 0; 883*bb9b6b3fSSheshadri Vasudevan if (begsec != epp->ext_beg_sec) { 884*bb9b6b3fSSheshadri Vasudevan part->relsect = LE_32(begsec - epp->ext_beg_sec); 885*bb9b6b3fSSheshadri Vasudevan temp->numsect = endsec - begsec + 1; 886*bb9b6b3fSSheshadri Vasudevan part->numsect = LE_32(temp->numsect); 887*bb9b6b3fSSheshadri Vasudevan if (LE_32(part->relsect) > MAX_LOGDRIVE_OFFSET) { 888*bb9b6b3fSSheshadri Vasudevan temp->logdrive_offset = 0; 889*bb9b6b3fSSheshadri Vasudevan } else { 890*bb9b6b3fSSheshadri Vasudevan temp->abs_secnum = epp->ext_beg_sec; 891*bb9b6b3fSSheshadri Vasudevan temp->logdrive_offset = LE_32(part->relsect); 892*bb9b6b3fSSheshadri Vasudevan } 893*bb9b6b3fSSheshadri Vasudevan } 894*bb9b6b3fSSheshadri Vasudevan epp->first_ebr_is_null = 0; 895*bb9b6b3fSSheshadri Vasudevan epp->ld_head = temp; 896*bb9b6b3fSSheshadri Vasudevan epp->sorted_ld_head = temp; 897*bb9b6b3fSSheshadri Vasudevan epp->logical_drive_count = 1; 898*bb9b6b3fSSheshadri Vasudevan return; 899*bb9b6b3fSSheshadri Vasudevan } 900*bb9b6b3fSSheshadri Vasudevan 901*bb9b6b3fSSheshadri Vasudevan if (temp->abs_secnum == epp->ext_beg_sec) { 902*bb9b6b3fSSheshadri Vasudevan part->relsect = LE_32(LE_32(part->relsect) - 1); 903*bb9b6b3fSSheshadri Vasudevan temp->logdrive_offset--; 904*bb9b6b3fSSheshadri Vasudevan temp->abs_secnum++; 905*bb9b6b3fSSheshadri Vasudevan } 906*bb9b6b3fSSheshadri Vasudevan 907*bb9b6b3fSSheshadri Vasudevan for (pre = cur = epp->ld_head; cur != NULL; pre = cur, cur = cur->next) 908*bb9b6b3fSSheshadri Vasudevan ; 909*bb9b6b3fSSheshadri Vasudevan 910*bb9b6b3fSSheshadri Vasudevan part = &pre->parts[1]; 911*bb9b6b3fSSheshadri Vasudevan part->bootid = 0; 912*bb9b6b3fSSheshadri Vasudevan part->systid = LE_8(EXTDOS); 913*bb9b6b3fSSheshadri Vasudevan part->relsect = LE_32(temp->abs_secnum - epp->ext_beg_sec); 914*bb9b6b3fSSheshadri Vasudevan part->numsect = LE_32(temp->numsect + temp->logdrive_offset); 915*bb9b6b3fSSheshadri Vasudevan 916*bb9b6b3fSSheshadri Vasudevan fdisk_set_CHS_values(epp, part); 917*bb9b6b3fSSheshadri Vasudevan 918*bb9b6b3fSSheshadri Vasudevan pre->next = temp; 919*bb9b6b3fSSheshadri Vasudevan pre->modified = FDISK_MAJOR_WRITE; 920*bb9b6b3fSSheshadri Vasudevan epp->logical_drive_count++; 921*bb9b6b3fSSheshadri Vasudevan fdisk_ext_place_in_sorted_list(epp, temp); 922*bb9b6b3fSSheshadri Vasudevan } 923*bb9b6b3fSSheshadri Vasudevan 924*bb9b6b3fSSheshadri Vasudevan /* 925*bb9b6b3fSSheshadri Vasudevan * There are 2 cases that need to be handled. 926*bb9b6b3fSSheshadri Vasudevan * 1. Deleting the first extended partition : 927*bb9b6b3fSSheshadri Vasudevan * The peculiarity of this case is that the offset of the first extended 928*bb9b6b3fSSheshadri Vasudevan * partition is always indicated by the entry in the master boot record. 929*bb9b6b3fSSheshadri Vasudevan * (MBR). This never changes, unless the extended partition itself is 930*bb9b6b3fSSheshadri Vasudevan * deleted. Hence, the location of the first EBR is fixed. 931*bb9b6b3fSSheshadri Vasudevan * It is only the logical drive which is deleted. This first EBR now gives 932*bb9b6b3fSSheshadri Vasudevan * information of the next logical drive and the info about the subsequent 933*bb9b6b3fSSheshadri Vasudevan * extended partition. Hence the "relsect" of the first EBR is modified to 934*bb9b6b3fSSheshadri Vasudevan * point to the next logical drive. 935*bb9b6b3fSSheshadri Vasudevan * 936*bb9b6b3fSSheshadri Vasudevan * 2. Deleting an intermediate extended partition. 937*bb9b6b3fSSheshadri Vasudevan * This is quite normal and follows the semantics of a normal linked list 938*bb9b6b3fSSheshadri Vasudevan * delete operation. The node being deleted has the information about the 939*bb9b6b3fSSheshadri Vasudevan * logical drive that it houses and the location and the size of the next 940*bb9b6b3fSSheshadri Vasudevan * extended partition. This informationis transferred to the node previous 941*bb9b6b3fSSheshadri Vasudevan * to the node being deleted. 942*bb9b6b3fSSheshadri Vasudevan * 943*bb9b6b3fSSheshadri Vasudevan */ 944*bb9b6b3fSSheshadri Vasudevan 945*bb9b6b3fSSheshadri Vasudevan void 946*bb9b6b3fSSheshadri Vasudevan fdisk_delete_logical_drive(ext_part_t *epp, int pno) 947*bb9b6b3fSSheshadri Vasudevan { 948*bb9b6b3fSSheshadri Vasudevan logical_drive_t *pre, *cur; 949*bb9b6b3fSSheshadri Vasudevan int i; 950*bb9b6b3fSSheshadri Vasudevan 951*bb9b6b3fSSheshadri Vasudevan i = FD_NUMPART + 1; 952*bb9b6b3fSSheshadri Vasudevan pre = cur = epp->ld_head; 953*bb9b6b3fSSheshadri Vasudevan for (; i < pno; i++) { 954*bb9b6b3fSSheshadri Vasudevan pre = cur; 955*bb9b6b3fSSheshadri Vasudevan cur = cur->next; 956*bb9b6b3fSSheshadri Vasudevan } 957*bb9b6b3fSSheshadri Vasudevan 958*bb9b6b3fSSheshadri Vasudevan if (cur == epp->ld_head) { 959*bb9b6b3fSSheshadri Vasudevan /* Deleting the first logical drive */ 960*bb9b6b3fSSheshadri Vasudevan if (cur->next == NULL) { 961*bb9b6b3fSSheshadri Vasudevan /* Deleting the only logical drive left */ 962*bb9b6b3fSSheshadri Vasudevan free(cur); 963*bb9b6b3fSSheshadri Vasudevan epp->ld_head = NULL; 964*bb9b6b3fSSheshadri Vasudevan epp->sorted_ld_head = NULL; 965*bb9b6b3fSSheshadri Vasudevan epp->logical_drive_count = 0; 966*bb9b6b3fSSheshadri Vasudevan epp->first_ebr_is_null = 1; 967*bb9b6b3fSSheshadri Vasudevan } else { 968*bb9b6b3fSSheshadri Vasudevan pre = epp->ld_head; 969*bb9b6b3fSSheshadri Vasudevan cur = pre->next; 970*bb9b6b3fSSheshadri Vasudevan cur->parts[0].relsect = 971*bb9b6b3fSSheshadri Vasudevan LE_32(LE_32(cur->parts[0].relsect) + 972*bb9b6b3fSSheshadri Vasudevan LE_32(pre->parts[1].relsect)); 973*bb9b6b3fSSheshadri Vasudevan /* Corner case when partitions are out of order */ 974*bb9b6b3fSSheshadri Vasudevan if ((pre->abs_secnum != epp->ext_beg_sec) && 975*bb9b6b3fSSheshadri Vasudevan (cur->abs_secnum == epp->ext_beg_sec + 1)) { 976*bb9b6b3fSSheshadri Vasudevan cur->logdrive_offset++; 977*bb9b6b3fSSheshadri Vasudevan cur->abs_secnum = epp->ext_beg_sec; 978*bb9b6b3fSSheshadri Vasudevan } else { 979*bb9b6b3fSSheshadri Vasudevan cur->abs_secnum = LE_32(cur->parts[0].relsect) + 980*bb9b6b3fSSheshadri Vasudevan epp->ext_beg_sec; 981*bb9b6b3fSSheshadri Vasudevan cur->logdrive_offset = 0; 982*bb9b6b3fSSheshadri Vasudevan } 983*bb9b6b3fSSheshadri Vasudevan fdisk_ext_remove_from_sorted_list(epp, pre); 984*bb9b6b3fSSheshadri Vasudevan epp->ld_head = cur; 985*bb9b6b3fSSheshadri Vasudevan epp->ld_head->modified = FDISK_MAJOR_WRITE; 986*bb9b6b3fSSheshadri Vasudevan epp->logical_drive_count--; 987*bb9b6b3fSSheshadri Vasudevan free(pre); 988*bb9b6b3fSSheshadri Vasudevan } 989*bb9b6b3fSSheshadri Vasudevan } else { 990*bb9b6b3fSSheshadri Vasudevan pre->parts[1] = cur->parts[1]; 991*bb9b6b3fSSheshadri Vasudevan pre->next = cur->next; 992*bb9b6b3fSSheshadri Vasudevan fdisk_ext_remove_from_sorted_list(epp, cur); 993*bb9b6b3fSSheshadri Vasudevan pre->modified = FDISK_MAJOR_WRITE; 994*bb9b6b3fSSheshadri Vasudevan free(cur); 995*bb9b6b3fSSheshadri Vasudevan epp->logical_drive_count--; 996*bb9b6b3fSSheshadri Vasudevan } 997*bb9b6b3fSSheshadri Vasudevan } 998*bb9b6b3fSSheshadri Vasudevan 999*bb9b6b3fSSheshadri Vasudevan static void 1000*bb9b6b3fSSheshadri Vasudevan fdisk_set_CHS_values(ext_part_t *epp, struct ipart *part) 1001*bb9b6b3fSSheshadri Vasudevan { 1002*bb9b6b3fSSheshadri Vasudevan uint32_t lba, cy, hd, sc; 1003*bb9b6b3fSSheshadri Vasudevan uint32_t sectors = epp->disk_geom.virt_sec; 1004*bb9b6b3fSSheshadri Vasudevan uint32_t heads = epp->disk_geom.virt_heads; 1005*bb9b6b3fSSheshadri Vasudevan 1006*bb9b6b3fSSheshadri Vasudevan lba = LE_32(part->relsect) + epp->ext_beg_sec; 1007*bb9b6b3fSSheshadri Vasudevan if (lba >= heads * sectors * MAX_CYL) { 1008*bb9b6b3fSSheshadri Vasudevan /* 1009*bb9b6b3fSSheshadri Vasudevan * the lba address cannot be expressed in CHS value 1010*bb9b6b3fSSheshadri Vasudevan * so store the maximum CHS field values in the CHS fields. 1011*bb9b6b3fSSheshadri Vasudevan */ 1012*bb9b6b3fSSheshadri Vasudevan cy = MAX_CYL + 1; 1013*bb9b6b3fSSheshadri Vasudevan hd = MAX_HEAD; 1014*bb9b6b3fSSheshadri Vasudevan sc = MAX_SECT; 1015*bb9b6b3fSSheshadri Vasudevan } else { 1016*bb9b6b3fSSheshadri Vasudevan cy = lba / sectors / heads; 1017*bb9b6b3fSSheshadri Vasudevan hd = lba / sectors % heads; 1018*bb9b6b3fSSheshadri Vasudevan sc = lba % sectors + 1; 1019*bb9b6b3fSSheshadri Vasudevan } 1020*bb9b6b3fSSheshadri Vasudevan 1021*bb9b6b3fSSheshadri Vasudevan part->begcyl = cy & 0xff; 1022*bb9b6b3fSSheshadri Vasudevan part->beghead = (uchar_t)hd; 1023*bb9b6b3fSSheshadri Vasudevan part->begsect = (uchar_t)(((cy >> 2) & 0xc0) | sc); 1024*bb9b6b3fSSheshadri Vasudevan 1025*bb9b6b3fSSheshadri Vasudevan /* 1026*bb9b6b3fSSheshadri Vasudevan * This code is identical to the code above 1027*bb9b6b3fSSheshadri Vasudevan * except that it works on ending CHS values 1028*bb9b6b3fSSheshadri Vasudevan */ 1029*bb9b6b3fSSheshadri Vasudevan lba += LE_32(part->numsect - 1); 1030*bb9b6b3fSSheshadri Vasudevan if (lba >= heads * sectors * MAX_CYL) { 1031*bb9b6b3fSSheshadri Vasudevan cy = MAX_CYL + 1; 1032*bb9b6b3fSSheshadri Vasudevan hd = MAX_HEAD; 1033*bb9b6b3fSSheshadri Vasudevan sc = MAX_SECT; 1034*bb9b6b3fSSheshadri Vasudevan } else { 1035*bb9b6b3fSSheshadri Vasudevan cy = lba / sectors / heads; 1036*bb9b6b3fSSheshadri Vasudevan hd = lba / sectors % heads; 1037*bb9b6b3fSSheshadri Vasudevan sc = lba % sectors + 1; 1038*bb9b6b3fSSheshadri Vasudevan } 1039*bb9b6b3fSSheshadri Vasudevan part->endcyl = cy & 0xff; 1040*bb9b6b3fSSheshadri Vasudevan part->endhead = (uchar_t)hd; 1041*bb9b6b3fSSheshadri Vasudevan part->endsect = (uchar_t)(((cy >> 2) & 0xc0) | sc); 1042*bb9b6b3fSSheshadri Vasudevan } 1043*bb9b6b3fSSheshadri Vasudevan 1044*bb9b6b3fSSheshadri Vasudevan static int 1045*bb9b6b3fSSheshadri Vasudevan read_modify_write_ebr(ext_part_t *epp, unsigned char *ebr_buf, 1046*bb9b6b3fSSheshadri Vasudevan struct ipart *ebr_tab, uint32_t sec_offset) 1047*bb9b6b3fSSheshadri Vasudevan { 1048*bb9b6b3fSSheshadri Vasudevan off_t seek_offset; 1049*bb9b6b3fSSheshadri Vasudevan int sectsize = epp->disk_geom.sectsize; 1050*bb9b6b3fSSheshadri Vasudevan 1051*bb9b6b3fSSheshadri Vasudevan seek_offset = (off_t)sec_offset * sectsize; 1052*bb9b6b3fSSheshadri Vasudevan 1053*bb9b6b3fSSheshadri Vasudevan if (lseek(epp->dev_fd, seek_offset, SEEK_SET) < 0) { 1054*bb9b6b3fSSheshadri Vasudevan return (EIO); 1055*bb9b6b3fSSheshadri Vasudevan } 1056*bb9b6b3fSSheshadri Vasudevan if (read(epp->dev_fd, ebr_buf, sectsize) < sectsize) { 1057*bb9b6b3fSSheshadri Vasudevan return (EIO); 1058*bb9b6b3fSSheshadri Vasudevan } 1059*bb9b6b3fSSheshadri Vasudevan 1060*bb9b6b3fSSheshadri Vasudevan bzero(&ebr_buf[FDISK_PART_TABLE_START], 4 * sizeof (struct ipart)); 1061*bb9b6b3fSSheshadri Vasudevan if (ebr_tab != NULL) { 1062*bb9b6b3fSSheshadri Vasudevan bcopy(ebr_tab, &ebr_buf[FDISK_PART_TABLE_START], 1063*bb9b6b3fSSheshadri Vasudevan 2 * sizeof (struct ipart)); 1064*bb9b6b3fSSheshadri Vasudevan } 1065*bb9b6b3fSSheshadri Vasudevan ebr_buf[510] = 0x55; 1066*bb9b6b3fSSheshadri Vasudevan ebr_buf[511] = 0xAA; 1067*bb9b6b3fSSheshadri Vasudevan if (lseek(epp->dev_fd, seek_offset, SEEK_SET) < 0) { 1068*bb9b6b3fSSheshadri Vasudevan return (EIO); 1069*bb9b6b3fSSheshadri Vasudevan } 1070*bb9b6b3fSSheshadri Vasudevan if (write(epp->dev_fd, ebr_buf, sectsize) < sectsize) { 1071*bb9b6b3fSSheshadri Vasudevan return (EIO); 1072*bb9b6b3fSSheshadri Vasudevan } 1073*bb9b6b3fSSheshadri Vasudevan return (0); 1074*bb9b6b3fSSheshadri Vasudevan } 1075*bb9b6b3fSSheshadri Vasudevan 1076*bb9b6b3fSSheshadri Vasudevan /* 1077*bb9b6b3fSSheshadri Vasudevan * XXX - ZFS mounts not detected. Needs to come in as a feature. 1078*bb9b6b3fSSheshadri Vasudevan * Currently only /etc/mnttab entries are being checked 1079*bb9b6b3fSSheshadri Vasudevan */ 1080*bb9b6b3fSSheshadri Vasudevan int 1081*bb9b6b3fSSheshadri Vasudevan fdisk_mounted_logical_drives(ext_part_t *epp) 1082*bb9b6b3fSSheshadri Vasudevan { 1083*bb9b6b3fSSheshadri Vasudevan char *part_str, *canonp; 1084*bb9b6b3fSSheshadri Vasudevan char compare_pdev_str[PATH_MAX]; 1085*bb9b6b3fSSheshadri Vasudevan char compare_sdev_str[PATH_MAX]; 1086*bb9b6b3fSSheshadri Vasudevan FILE *fp; 1087*bb9b6b3fSSheshadri Vasudevan struct mnttab mt; 1088*bb9b6b3fSSheshadri Vasudevan int part; 1089*bb9b6b3fSSheshadri Vasudevan int look_for_mounted_slices = 0; 1090*bb9b6b3fSSheshadri Vasudevan uint32_t begsec, numsec; 1091*bb9b6b3fSSheshadri Vasudevan 1092*bb9b6b3fSSheshadri Vasudevan /* 1093*bb9b6b3fSSheshadri Vasudevan * Do not check for mounted logical drives for 1094*bb9b6b3fSSheshadri Vasudevan * devices other than /dev/rdsk/ 1095*bb9b6b3fSSheshadri Vasudevan */ 1096*bb9b6b3fSSheshadri Vasudevan if (strstr(epp->device_name, DEFAULT_PATH_PREFIX) == NULL) { 1097*bb9b6b3fSSheshadri Vasudevan return (0); 1098*bb9b6b3fSSheshadri Vasudevan } 1099*bb9b6b3fSSheshadri Vasudevan 1100*bb9b6b3fSSheshadri Vasudevan if ((fp = fopen(MNTTAB, "r")) == NULL) { 1101*bb9b6b3fSSheshadri Vasudevan return (ENOENT); 1102*bb9b6b3fSSheshadri Vasudevan } 1103*bb9b6b3fSSheshadri Vasudevan 1104*bb9b6b3fSSheshadri Vasudevan canonp = epp->device_name + strlen(DEFAULT_PATH_PREFIX); 1105*bb9b6b3fSSheshadri Vasudevan (void) snprintf(compare_pdev_str, PATH_MAX, "%s%s", "/dev/dsk/", 1106*bb9b6b3fSSheshadri Vasudevan canonp); 1107*bb9b6b3fSSheshadri Vasudevan part_str = strrchr(compare_pdev_str, 'p'); 1108*bb9b6b3fSSheshadri Vasudevan *(part_str + 1) = '\0'; 1109*bb9b6b3fSSheshadri Vasudevan (void) strcpy(compare_sdev_str, compare_pdev_str); 1110*bb9b6b3fSSheshadri Vasudevan part_str = strrchr(compare_sdev_str, 'p'); 1111*bb9b6b3fSSheshadri Vasudevan *part_str = 's'; 1112*bb9b6b3fSSheshadri Vasudevan 1113*bb9b6b3fSSheshadri Vasudevan if (fdisk_get_solaris_part(epp, &part, &begsec, &numsec) == 1114*bb9b6b3fSSheshadri Vasudevan FDISK_SUCCESS) { 1115*bb9b6b3fSSheshadri Vasudevan if (part > FD_NUMPART) { 1116*bb9b6b3fSSheshadri Vasudevan /* 1117*bb9b6b3fSSheshadri Vasudevan * Solaris partition is on a logical drive. Look for 1118*bb9b6b3fSSheshadri Vasudevan * mounted slices. 1119*bb9b6b3fSSheshadri Vasudevan */ 1120*bb9b6b3fSSheshadri Vasudevan look_for_mounted_slices = 1; 1121*bb9b6b3fSSheshadri Vasudevan } 1122*bb9b6b3fSSheshadri Vasudevan } 1123*bb9b6b3fSSheshadri Vasudevan 1124*bb9b6b3fSSheshadri Vasudevan while (getmntent(fp, &mt) == 0) { 1125*bb9b6b3fSSheshadri Vasudevan if (strstr(mt.mnt_special, compare_pdev_str) == NULL) { 1126*bb9b6b3fSSheshadri Vasudevan if (strstr(mt.mnt_special, compare_sdev_str) == NULL) { 1127*bb9b6b3fSSheshadri Vasudevan continue; 1128*bb9b6b3fSSheshadri Vasudevan } else { 1129*bb9b6b3fSSheshadri Vasudevan if (look_for_mounted_slices) { 1130*bb9b6b3fSSheshadri Vasudevan return (FDISK_EMOUNTED); 1131*bb9b6b3fSSheshadri Vasudevan } 1132*bb9b6b3fSSheshadri Vasudevan } 1133*bb9b6b3fSSheshadri Vasudevan } 1134*bb9b6b3fSSheshadri Vasudevan 1135*bb9b6b3fSSheshadri Vasudevan /* 1136*bb9b6b3fSSheshadri Vasudevan * Get the partition number that is mounted, which would be 1137*bb9b6b3fSSheshadri Vasudevan * found just beyond the last 'p' in the device string. 1138*bb9b6b3fSSheshadri Vasudevan * For example, in /dev/dsk/c0t0d0p12, partition number 12 1139*bb9b6b3fSSheshadri Vasudevan * is just beyond the last 'p'. 1140*bb9b6b3fSSheshadri Vasudevan */ 1141*bb9b6b3fSSheshadri Vasudevan part_str = strrchr(mt.mnt_special, 'p'); 1142*bb9b6b3fSSheshadri Vasudevan if (part_str != NULL) { 1143*bb9b6b3fSSheshadri Vasudevan part_str++; 1144*bb9b6b3fSSheshadri Vasudevan part = atoi(part_str); 1145*bb9b6b3fSSheshadri Vasudevan /* Extended partition numbers start from 5 */ 1146*bb9b6b3fSSheshadri Vasudevan if (part >= 5) { 1147*bb9b6b3fSSheshadri Vasudevan return (FDISK_EMOUNTED); 1148*bb9b6b3fSSheshadri Vasudevan } 1149*bb9b6b3fSSheshadri Vasudevan } 1150*bb9b6b3fSSheshadri Vasudevan } 1151*bb9b6b3fSSheshadri Vasudevan return (0); 1152*bb9b6b3fSSheshadri Vasudevan } 1153*bb9b6b3fSSheshadri Vasudevan 1154*bb9b6b3fSSheshadri Vasudevan int 1155*bb9b6b3fSSheshadri Vasudevan fdisk_commit_ext_part(ext_part_t *epp) 1156*bb9b6b3fSSheshadri Vasudevan { 1157*bb9b6b3fSSheshadri Vasudevan logical_drive_t *temp; 1158*bb9b6b3fSSheshadri Vasudevan int wflag = 0; /* write flag */ 1159*bb9b6b3fSSheshadri Vasudevan int rval; 1160*bb9b6b3fSSheshadri Vasudevan int sectsize = epp->disk_geom.sectsize; 1161*bb9b6b3fSSheshadri Vasudevan unsigned char *ebr_buf; 1162*bb9b6b3fSSheshadri Vasudevan int ld_count; 1163*bb9b6b3fSSheshadri Vasudevan uint32_t abs_secnum; 1164*bb9b6b3fSSheshadri Vasudevan int check_mounts = 0; 1165*bb9b6b3fSSheshadri Vasudevan 1166*bb9b6b3fSSheshadri Vasudevan if ((ebr_buf = (unsigned char *)malloc(sectsize)) == NULL) { 1167*bb9b6b3fSSheshadri Vasudevan return (ENOMEM); 1168*bb9b6b3fSSheshadri Vasudevan } 1169*bb9b6b3fSSheshadri Vasudevan 1170*bb9b6b3fSSheshadri Vasudevan if (epp->first_ebr_is_null) { 1171*bb9b6b3fSSheshadri Vasudevan /* 1172*bb9b6b3fSSheshadri Vasudevan * Indicator that the extended partition as a whole was 1173*bb9b6b3fSSheshadri Vasudevan * modifies (either created or deleted. Must check for mounts 1174*bb9b6b3fSSheshadri Vasudevan * and must commit 1175*bb9b6b3fSSheshadri Vasudevan */ 1176*bb9b6b3fSSheshadri Vasudevan check_mounts = 1; 1177*bb9b6b3fSSheshadri Vasudevan } 1178*bb9b6b3fSSheshadri Vasudevan 1179*bb9b6b3fSSheshadri Vasudevan /* 1180*bb9b6b3fSSheshadri Vasudevan * Pass1 through the logical drives to make sure that commit of minor 1181*bb9b6b3fSSheshadri Vasudevan * written block dont get held up due to mounts. 1182*bb9b6b3fSSheshadri Vasudevan */ 1183*bb9b6b3fSSheshadri Vasudevan for (temp = epp->ld_head; temp != NULL; temp = temp->next) { 1184*bb9b6b3fSSheshadri Vasudevan if (temp == epp->ld_head) { 1185*bb9b6b3fSSheshadri Vasudevan abs_secnum = epp->ext_beg_sec; 1186*bb9b6b3fSSheshadri Vasudevan } else { 1187*bb9b6b3fSSheshadri Vasudevan abs_secnum = temp->abs_secnum; 1188*bb9b6b3fSSheshadri Vasudevan } 1189*bb9b6b3fSSheshadri Vasudevan if (temp->modified == FDISK_MINOR_WRITE) { 1190*bb9b6b3fSSheshadri Vasudevan rval = read_modify_write_ebr(epp, ebr_buf, 1191*bb9b6b3fSSheshadri Vasudevan temp->parts, abs_secnum); 1192*bb9b6b3fSSheshadri Vasudevan if (rval) { 1193*bb9b6b3fSSheshadri Vasudevan goto error; 1194*bb9b6b3fSSheshadri Vasudevan } 1195*bb9b6b3fSSheshadri Vasudevan temp->modified = 0; 1196*bb9b6b3fSSheshadri Vasudevan } else if (temp->modified == FDISK_MAJOR_WRITE) { 1197*bb9b6b3fSSheshadri Vasudevan check_mounts = 1; 1198*bb9b6b3fSSheshadri Vasudevan } 1199*bb9b6b3fSSheshadri Vasudevan } 1200*bb9b6b3fSSheshadri Vasudevan 1201*bb9b6b3fSSheshadri Vasudevan if (!check_mounts) { 1202*bb9b6b3fSSheshadri Vasudevan goto skip_check_mounts; 1203*bb9b6b3fSSheshadri Vasudevan } 1204*bb9b6b3fSSheshadri Vasudevan 1205*bb9b6b3fSSheshadri Vasudevan if ((rval = fdisk_mounted_logical_drives(epp)) != 0) { 1206*bb9b6b3fSSheshadri Vasudevan /* One/more extended partitions are mounted */ 1207*bb9b6b3fSSheshadri Vasudevan if (ebr_buf) { 1208*bb9b6b3fSSheshadri Vasudevan free(ebr_buf); 1209*bb9b6b3fSSheshadri Vasudevan } 1210*bb9b6b3fSSheshadri Vasudevan return (rval); 1211*bb9b6b3fSSheshadri Vasudevan } 1212*bb9b6b3fSSheshadri Vasudevan 1213*bb9b6b3fSSheshadri Vasudevan skip_check_mounts: 1214*bb9b6b3fSSheshadri Vasudevan 1215*bb9b6b3fSSheshadri Vasudevan if (epp->first_ebr_is_null) { 1216*bb9b6b3fSSheshadri Vasudevan rval = read_modify_write_ebr(epp, ebr_buf, NULL, 1217*bb9b6b3fSSheshadri Vasudevan epp->ext_beg_sec); 1218*bb9b6b3fSSheshadri Vasudevan if (rval) { 1219*bb9b6b3fSSheshadri Vasudevan goto error; 1220*bb9b6b3fSSheshadri Vasudevan } 1221*bb9b6b3fSSheshadri Vasudevan wflag = 1; 1222*bb9b6b3fSSheshadri Vasudevan ld_count = 0; 1223*bb9b6b3fSSheshadri Vasudevan } else { 1224*bb9b6b3fSSheshadri Vasudevan if (epp->logical_drive_count == 0) { 1225*bb9b6b3fSSheshadri Vasudevan /* 1226*bb9b6b3fSSheshadri Vasudevan * Can hit this case when there is just an extended 1227*bb9b6b3fSSheshadri Vasudevan * partition with no logical drives, and the user 1228*bb9b6b3fSSheshadri Vasudevan * committed without making any changes 1229*bb9b6b3fSSheshadri Vasudevan * We dont have anything to commit. Return success 1230*bb9b6b3fSSheshadri Vasudevan */ 1231*bb9b6b3fSSheshadri Vasudevan if (ebr_buf) { 1232*bb9b6b3fSSheshadri Vasudevan free(ebr_buf); 1233*bb9b6b3fSSheshadri Vasudevan } 1234*bb9b6b3fSSheshadri Vasudevan return (FDISK_SUCCESS); 1235*bb9b6b3fSSheshadri Vasudevan } 1236*bb9b6b3fSSheshadri Vasudevan 1237*bb9b6b3fSSheshadri Vasudevan /* 1238*bb9b6b3fSSheshadri Vasudevan * Make sure that the first EBR is written with the first 1239*bb9b6b3fSSheshadri Vasudevan * logical drive's data, which might not be the first in disk 1240*bb9b6b3fSSheshadri Vasudevan * order. 1241*bb9b6b3fSSheshadri Vasudevan */ 1242*bb9b6b3fSSheshadri Vasudevan for (temp = epp->ld_head, ld_count = 0; temp != NULL; 1243*bb9b6b3fSSheshadri Vasudevan temp = temp->next, ld_count++) { 1244*bb9b6b3fSSheshadri Vasudevan if (ld_count == 0) { 1245*bb9b6b3fSSheshadri Vasudevan abs_secnum = epp->ext_beg_sec; 1246*bb9b6b3fSSheshadri Vasudevan } else { 1247*bb9b6b3fSSheshadri Vasudevan abs_secnum = temp->abs_secnum; 1248*bb9b6b3fSSheshadri Vasudevan } 1249*bb9b6b3fSSheshadri Vasudevan if (temp->modified) { 1250*bb9b6b3fSSheshadri Vasudevan rval = read_modify_write_ebr(epp, ebr_buf, 1251*bb9b6b3fSSheshadri Vasudevan temp->parts, abs_secnum); 1252*bb9b6b3fSSheshadri Vasudevan if (rval) { 1253*bb9b6b3fSSheshadri Vasudevan if (ld_count) { 1254*bb9b6b3fSSheshadri Vasudevan /* 1255*bb9b6b3fSSheshadri Vasudevan * There was atleast one 1256*bb9b6b3fSSheshadri Vasudevan * write to the disk before 1257*bb9b6b3fSSheshadri Vasudevan * this failure. Make sure that 1258*bb9b6b3fSSheshadri Vasudevan * the kernel is notified. 1259*bb9b6b3fSSheshadri Vasudevan * Issue the ioctl. 1260*bb9b6b3fSSheshadri Vasudevan */ 1261*bb9b6b3fSSheshadri Vasudevan break; 1262*bb9b6b3fSSheshadri Vasudevan } 1263*bb9b6b3fSSheshadri Vasudevan goto error; 1264*bb9b6b3fSSheshadri Vasudevan } 1265*bb9b6b3fSSheshadri Vasudevan if ((!wflag) && (temp->modified == 1266*bb9b6b3fSSheshadri Vasudevan FDISK_MAJOR_WRITE)) { 1267*bb9b6b3fSSheshadri Vasudevan wflag = 1; 1268*bb9b6b3fSSheshadri Vasudevan } 1269*bb9b6b3fSSheshadri Vasudevan } 1270*bb9b6b3fSSheshadri Vasudevan } 1271*bb9b6b3fSSheshadri Vasudevan 1272*bb9b6b3fSSheshadri Vasudevan if (wflag == 0) { 1273*bb9b6b3fSSheshadri Vasudevan /* No changes made */ 1274*bb9b6b3fSSheshadri Vasudevan rval = FDISK_SUCCESS; 1275*bb9b6b3fSSheshadri Vasudevan goto error; 1276*bb9b6b3fSSheshadri Vasudevan } 1277*bb9b6b3fSSheshadri Vasudevan } 1278*bb9b6b3fSSheshadri Vasudevan 1279*bb9b6b3fSSheshadri Vasudevan /* Issue ioctl to the driver to update extended partition info */ 1280*bb9b6b3fSSheshadri Vasudevan rval = ioctl(epp->dev_fd, DKIOCSETEXTPART); 1281*bb9b6b3fSSheshadri Vasudevan 1282*bb9b6b3fSSheshadri Vasudevan /* 1283*bb9b6b3fSSheshadri Vasudevan * Certain devices ex:lofi do not support DKIOCSETEXTPART. 1284*bb9b6b3fSSheshadri Vasudevan * Extended partitions are still created on these devices. 1285*bb9b6b3fSSheshadri Vasudevan */ 1286*bb9b6b3fSSheshadri Vasudevan if (errno == ENOTTY) 1287*bb9b6b3fSSheshadri Vasudevan rval = FDISK_SUCCESS; 1288*bb9b6b3fSSheshadri Vasudevan 1289*bb9b6b3fSSheshadri Vasudevan error: 1290*bb9b6b3fSSheshadri Vasudevan if (ebr_buf) { 1291*bb9b6b3fSSheshadri Vasudevan free(ebr_buf); 1292*bb9b6b3fSSheshadri Vasudevan } 1293*bb9b6b3fSSheshadri Vasudevan return (rval); 1294*bb9b6b3fSSheshadri Vasudevan } 1295*bb9b6b3fSSheshadri Vasudevan 1296*bb9b6b3fSSheshadri Vasudevan int 1297*bb9b6b3fSSheshadri Vasudevan fdisk_init_ext_part(ext_part_t *epp, uint32_t rsect, uint32_t nsect) 1298*bb9b6b3fSSheshadri Vasudevan { 1299*bb9b6b3fSSheshadri Vasudevan epp->first_ebr_is_null = 1; 1300*bb9b6b3fSSheshadri Vasudevan epp->corrupt_logical_drives = 0; 1301*bb9b6b3fSSheshadri Vasudevan epp->logical_drive_count = 0; 1302*bb9b6b3fSSheshadri Vasudevan epp->ext_beg_sec = rsect; 1303*bb9b6b3fSSheshadri Vasudevan epp->ext_end_sec = rsect + nsect - 1; 1304*bb9b6b3fSSheshadri Vasudevan epp->ext_beg_cyl = FDISK_SECT_TO_CYL(epp, epp->ext_beg_sec); 1305*bb9b6b3fSSheshadri Vasudevan epp->ext_end_cyl = FDISK_SECT_TO_CYL(epp, epp->ext_end_sec); 1306*bb9b6b3fSSheshadri Vasudevan epp->invalid_bb_sig[0] = 0; 1307*bb9b6b3fSSheshadri Vasudevan return (0); 1308*bb9b6b3fSSheshadri Vasudevan } 1309*bb9b6b3fSSheshadri Vasudevan 1310*bb9b6b3fSSheshadri Vasudevan int 1311*bb9b6b3fSSheshadri Vasudevan fdisk_delete_ext_part(ext_part_t *epp) 1312*bb9b6b3fSSheshadri Vasudevan { 1313*bb9b6b3fSSheshadri Vasudevan epp->first_ebr_is_null = 1; 1314*bb9b6b3fSSheshadri Vasudevan /* Clear the logical drive information */ 1315*bb9b6b3fSSheshadri Vasudevan fdisk_free_ld_nodes(epp); 1316*bb9b6b3fSSheshadri Vasudevan epp->logical_drive_count = 0; 1317*bb9b6b3fSSheshadri Vasudevan epp->corrupt_logical_drives = 0; 1318*bb9b6b3fSSheshadri Vasudevan epp->invalid_bb_sig[0] = 0; 1319*bb9b6b3fSSheshadri Vasudevan return (0); 1320*bb9b6b3fSSheshadri Vasudevan } 1321*bb9b6b3fSSheshadri Vasudevan 1322*bb9b6b3fSSheshadri Vasudevan int 1323*bb9b6b3fSSheshadri Vasudevan fdisk_get_disk_geom(ext_part_t *epp, int type, int what) 1324*bb9b6b3fSSheshadri Vasudevan { 1325*bb9b6b3fSSheshadri Vasudevan switch (type) { 1326*bb9b6b3fSSheshadri Vasudevan case PHYSGEOM: 1327*bb9b6b3fSSheshadri Vasudevan switch (what) { 1328*bb9b6b3fSSheshadri Vasudevan case NCYL: 1329*bb9b6b3fSSheshadri Vasudevan return ((int)epp->disk_geom.phys_cyl); 1330*bb9b6b3fSSheshadri Vasudevan case NHEADS: 1331*bb9b6b3fSSheshadri Vasudevan return ((int)epp->disk_geom.phys_heads); 1332*bb9b6b3fSSheshadri Vasudevan case NSECTPT: 1333*bb9b6b3fSSheshadri Vasudevan return ((int)epp->disk_geom.phys_sec); 1334*bb9b6b3fSSheshadri Vasudevan case SSIZE: 1335*bb9b6b3fSSheshadri Vasudevan return ((int)epp->disk_geom.sectsize); 1336*bb9b6b3fSSheshadri Vasudevan case ACYL: 1337*bb9b6b3fSSheshadri Vasudevan return ((int)epp->disk_geom.alt_cyl); 1338*bb9b6b3fSSheshadri Vasudevan default: 1339*bb9b6b3fSSheshadri Vasudevan return (EINVAL); 1340*bb9b6b3fSSheshadri Vasudevan } 1341*bb9b6b3fSSheshadri Vasudevan case VIRTGEOM: 1342*bb9b6b3fSSheshadri Vasudevan switch (what) { 1343*bb9b6b3fSSheshadri Vasudevan case NCYL: 1344*bb9b6b3fSSheshadri Vasudevan return ((int)epp->disk_geom.virt_cyl); 1345*bb9b6b3fSSheshadri Vasudevan case NHEADS: 1346*bb9b6b3fSSheshadri Vasudevan return ((int)epp->disk_geom.virt_heads); 1347*bb9b6b3fSSheshadri Vasudevan case NSECTPT: 1348*bb9b6b3fSSheshadri Vasudevan return ((int)epp->disk_geom.virt_sec); 1349*bb9b6b3fSSheshadri Vasudevan case SSIZE: 1350*bb9b6b3fSSheshadri Vasudevan return ((int)epp->disk_geom.sectsize); 1351*bb9b6b3fSSheshadri Vasudevan case ACYL: 1352*bb9b6b3fSSheshadri Vasudevan return ((int)epp->disk_geom.alt_cyl); 1353*bb9b6b3fSSheshadri Vasudevan default: 1354*bb9b6b3fSSheshadri Vasudevan return (EINVAL); 1355*bb9b6b3fSSheshadri Vasudevan } 1356*bb9b6b3fSSheshadri Vasudevan default: 1357*bb9b6b3fSSheshadri Vasudevan return (EINVAL); 1358*bb9b6b3fSSheshadri Vasudevan } 1359*bb9b6b3fSSheshadri Vasudevan } 1360*bb9b6b3fSSheshadri Vasudevan 1361*bb9b6b3fSSheshadri Vasudevan int 1362*bb9b6b3fSSheshadri Vasudevan fdisk_invalid_bb_sig(ext_part_t *epp, uchar_t **bbsig_arr) 1363*bb9b6b3fSSheshadri Vasudevan { 1364*bb9b6b3fSSheshadri Vasudevan *bbsig_arr = &(epp->invalid_bb_sig[0]); 1365*bb9b6b3fSSheshadri Vasudevan return (epp->invalid_bb_sig[0]); 1366*bb9b6b3fSSheshadri Vasudevan } 1367