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