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