17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*cfcc56e0SMark Logan * Common Development and Distribution License (the "License"). 6*cfcc56e0SMark Logan * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 22*cfcc56e0SMark Logan * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 24*cfcc56e0SMark Logan * 25*cfcc56e0SMark Logan * copyright (c) 1990, 1991 UNIX System Laboratories, Inc. 26*cfcc56e0SMark Logan * copyright (c) 1984, 1986, 1987, 1988, 1989, 1990 AT&T 27*cfcc56e0SMark Logan * All rights reserved. 287c478bd9Sstevel@tonic-gate */ 297c478bd9Sstevel@tonic-gate 307c478bd9Sstevel@tonic-gate /* 317c478bd9Sstevel@tonic-gate * Copyrighted as an unpublished work. 327c478bd9Sstevel@tonic-gate * (c) Copyright INTERACTIVE Systems Corporation 1986, 1988, 1990 337c478bd9Sstevel@tonic-gate * All rights reserved. 347c478bd9Sstevel@tonic-gate */ 357c478bd9Sstevel@tonic-gate 367c478bd9Sstevel@tonic-gate #include <sys/types.h> 377c478bd9Sstevel@tonic-gate #include <ctype.h> 387c478bd9Sstevel@tonic-gate #include <fcntl.h> 397c478bd9Sstevel@tonic-gate #include <malloc.h> 407c478bd9Sstevel@tonic-gate #include <sys/stat.h> 417c478bd9Sstevel@tonic-gate #include <sys/swap.h> 427c478bd9Sstevel@tonic-gate #include <stdio.h> 43*cfcc56e0SMark Logan #include <stdlib.h> 44*cfcc56e0SMark Logan #include <unistd.h> 457c478bd9Sstevel@tonic-gate #include <string.h> 467c478bd9Sstevel@tonic-gate #include <sys/vtoc.h> 477c478bd9Sstevel@tonic-gate #include <sys/param.h> 487c478bd9Sstevel@tonic-gate #include <sys/dkio.h> 497c478bd9Sstevel@tonic-gate #include <sys/dktp/altsctr.h> 507c478bd9Sstevel@tonic-gate #include <sys/dktp/fdisk.h> 517c478bd9Sstevel@tonic-gate #include "badsec.h" 527c478bd9Sstevel@tonic-gate 537c478bd9Sstevel@tonic-gate #define FAILURE 0 547c478bd9Sstevel@tonic-gate #define SUCCESS 1 557c478bd9Sstevel@tonic-gate 567c478bd9Sstevel@tonic-gate #define CMD_READ 0 577c478bd9Sstevel@tonic-gate #define CMD_WRITE 1 587c478bd9Sstevel@tonic-gate 597c478bd9Sstevel@tonic-gate struct badsec_lst *badsl_chain; 607c478bd9Sstevel@tonic-gate int badsl_chain_cnt; 617c478bd9Sstevel@tonic-gate struct badsec_lst *gbadsl_chain; 627c478bd9Sstevel@tonic-gate int gbadsl_chain_cnt; 637c478bd9Sstevel@tonic-gate 647c478bd9Sstevel@tonic-gate extern struct dk_geom dkg; 657c478bd9Sstevel@tonic-gate extern int alts_fd; 667c478bd9Sstevel@tonic-gate 677c478bd9Sstevel@tonic-gate struct alts_mempart alts_part = { 0, NULL, 0 }; 687c478bd9Sstevel@tonic-gate struct alts_mempart *ap = &alts_part; /* pointer to incore alts tables */ 697c478bd9Sstevel@tonic-gate 70*cfcc56e0SMark Logan static void read_altsctr(struct extpartition *part, int badok); 71052b6e8aSbg159949 static void chk_badsec(void); 72052b6e8aSbg159949 static void init_altsctr(void); 73052b6e8aSbg159949 void wr_altsctr(void); 74052b6e8aSbg159949 static void get_badsec(void); 75052b6e8aSbg159949 static int count_badsec(void); 76052b6e8aSbg159949 static void gen_alts_ent(void); 77052b6e8aSbg159949 static void assign_altsctr(void); 78052b6e8aSbg159949 static void expand_map(void); 79052b6e8aSbg159949 static void compress_map(void); 80*cfcc56e0SMark Logan static int altsmap_getbit(blkaddr_t badsec); 81*cfcc56e0SMark Logan static blkaddr_t altsmap_alloc(blkaddr_t srt_ind, blkaddr_t end_ind, 82*cfcc56e0SMark Logan int cnt, int dir); 83052b6e8aSbg159949 static void ent_sort(struct alts_ent buf[], int cnt); 84052b6e8aSbg159949 static void ent_compress(struct alts_ent buf[], int cnt); 85052b6e8aSbg159949 static int ent_merge( 86052b6e8aSbg159949 struct alts_ent buf[], 87052b6e8aSbg159949 struct alts_ent list1[], 88052b6e8aSbg159949 int lcnt1, 89052b6e8aSbg159949 struct alts_ent list2[], 90052b6e8aSbg159949 int lcnt2); 91052b6e8aSbg159949 static int ent_bsearch(struct alts_ent buf[], int cnt, struct alts_ent *key); 92*cfcc56e0SMark Logan static int chk_bad_altsctr(blkaddr_t badsec); 93*cfcc56e0SMark Logan int print_altsec(struct extpartition *part); 94*cfcc56e0SMark Logan int get_altsctr(int); 95052b6e8aSbg159949 static void print_altsctr(void); 96*cfcc56e0SMark Logan static int absdsk_io(int fd, uint_t srtsec, char *bufp, uint_t len, 97*cfcc56e0SMark Logan int ioflag); 98052b6e8aSbg159949 997c478bd9Sstevel@tonic-gate /* 1007c478bd9Sstevel@tonic-gate * updatebadsec () -- update bad sector/track mapping tables 1017c478bd9Sstevel@tonic-gate */ 102052b6e8aSbg159949 int 103*cfcc56e0SMark Logan updatebadsec(struct extpartition *part, int init_flag) 1047c478bd9Sstevel@tonic-gate { 1057c478bd9Sstevel@tonic-gate if (init_flag) 1067c478bd9Sstevel@tonic-gate ap->ap_flag |= ALTS_ADDPART; 1077c478bd9Sstevel@tonic-gate get_badsec(); 1087c478bd9Sstevel@tonic-gate read_altsctr(part, 1); 1097c478bd9Sstevel@tonic-gate ent_sort(ap->ap_gbadp, ap->ap_gbadcnt); 1107c478bd9Sstevel@tonic-gate ent_compress(ap->ap_gbadp, ap->ap_gbadcnt); 1117c478bd9Sstevel@tonic-gate gen_alts_ent(); 1127c478bd9Sstevel@tonic-gate compress_map(); 1137c478bd9Sstevel@tonic-gate return (SUCCESS); 1147c478bd9Sstevel@tonic-gate } 1157c478bd9Sstevel@tonic-gate 1167c478bd9Sstevel@tonic-gate /* 1177c478bd9Sstevel@tonic-gate * read_altsctr( ptr to alternate sector partition ) 1187c478bd9Sstevel@tonic-gate * -- read the alternate sector partition tables 1197c478bd9Sstevel@tonic-gate */ 120052b6e8aSbg159949 static void 121*cfcc56e0SMark Logan read_altsctr(struct extpartition *part, int badok) 1227c478bd9Sstevel@tonic-gate { 1237c478bd9Sstevel@tonic-gate if (ap->ap_tblp == NULL) { 1247c478bd9Sstevel@tonic-gate /* allocate buffer for the alts partition table (sector size) */ 1257c478bd9Sstevel@tonic-gate ap->ap_tbl_secsiz = byte_to_secsiz(ALTS_PARTTBL_SIZE, NBPSCTR); 1267c478bd9Sstevel@tonic-gate ap->ap_tblp = (struct alts_parttbl *)malloc(ap->ap_tbl_secsiz); 1277c478bd9Sstevel@tonic-gate if (ap->ap_tblp == NULL) { 128*cfcc56e0SMark Logan (void) fprintf(stderr, 129*cfcc56e0SMark Logan "Unable to malloc alternate partition table.\n"); 1307c478bd9Sstevel@tonic-gate exit(50); 1317c478bd9Sstevel@tonic-gate } 1327c478bd9Sstevel@tonic-gate 1337c478bd9Sstevel@tonic-gate /* allocate buffer for the alts partition map (sector size) */ 1347c478bd9Sstevel@tonic-gate /* buffers include the disk image bit map */ 1357c478bd9Sstevel@tonic-gate /* and the incore transformed char map */ 1367c478bd9Sstevel@tonic-gate 137*cfcc56e0SMark Logan if ((ap->ap_memmapp = (uchar_t *)malloc(part->p_size)) == NULL) { 138*cfcc56e0SMark Logan (void) fprintf(stderr, 139*cfcc56e0SMark Logan "Unable to malloc incore alternate partition map.\n"); 1407c478bd9Sstevel@tonic-gate exit(51); 1417c478bd9Sstevel@tonic-gate } 1427c478bd9Sstevel@tonic-gate ap->ap_tblp->alts_map_len = (part->p_size + 8 - 1) / 8; 143*cfcc56e0SMark Logan ap->ap_map_secsiz = byte_to_secsiz(ap->ap_tblp->alts_map_len, 144*cfcc56e0SMark Logan NBPSCTR); 1457c478bd9Sstevel@tonic-gate ap->ap_map_sectot = ap->ap_map_secsiz / NBPSCTR; 146*cfcc56e0SMark Logan if ((ap->ap_mapp = (uchar_t *)malloc(ap->ap_map_secsiz)) == NULL) { 147*cfcc56e0SMark Logan (void) fprintf(stderr, 148*cfcc56e0SMark Logan "Unable to malloc alternate partition map.\n"); 1497c478bd9Sstevel@tonic-gate exit(52); 1507c478bd9Sstevel@tonic-gate } 1517c478bd9Sstevel@tonic-gate /* clear the buffers to zero */ 152*cfcc56e0SMark Logan (void) memset(ap->ap_memmapp, 0, part->p_size); 153*cfcc56e0SMark Logan (void) memset(ap->ap_mapp, 0, ap->ap_map_secsiz); 1547c478bd9Sstevel@tonic-gate ap->part = *part; /* struct copy */ 1557c478bd9Sstevel@tonic-gate 1567c478bd9Sstevel@tonic-gate /* 1577c478bd9Sstevel@tonic-gate * if add alternate partition flag is set, then install the partition 1587c478bd9Sstevel@tonic-gate * otherwise read the alts partition info from disk 1597c478bd9Sstevel@tonic-gate * if failed, then assume the first installation 1607c478bd9Sstevel@tonic-gate */ 161*cfcc56e0SMark Logan if (ap->ap_flag & ALTS_ADDPART) { 162*cfcc56e0SMark Logan (void) fprintf(stderr, 163*cfcc56e0SMark Logan "WARNING: Manually initializing alternate table.\n"); 1647c478bd9Sstevel@tonic-gate init_altsctr(); 165*cfcc56e0SMark Logan } else { 1667c478bd9Sstevel@tonic-gate if (get_altsctr(badok) == SUCCESS) 1677c478bd9Sstevel@tonic-gate chk_badsec(); 1687c478bd9Sstevel@tonic-gate else 1697c478bd9Sstevel@tonic-gate init_altsctr(); 1707c478bd9Sstevel@tonic-gate } 1717c478bd9Sstevel@tonic-gate } 1727c478bd9Sstevel@tonic-gate } 1737c478bd9Sstevel@tonic-gate 1747c478bd9Sstevel@tonic-gate 1757c478bd9Sstevel@tonic-gate /* 1767c478bd9Sstevel@tonic-gate * checking duplicate bad sectors or bad sectors in ALTSCTR partition 1777c478bd9Sstevel@tonic-gate */ 178052b6e8aSbg159949 static void 179052b6e8aSbg159949 chk_badsec(void) 1807c478bd9Sstevel@tonic-gate { 181*cfcc56e0SMark Logan blkaddr_t badsec; 182*cfcc56e0SMark Logan blkaddr_t altsp_srtsec = ap->part.p_start; 183*cfcc56e0SMark Logan blkaddr_t altsp_endsec = ap->part.p_start + ap->part.p_size - 1; 1847c478bd9Sstevel@tonic-gate int cnt; 1857c478bd9Sstevel@tonic-gate int status; 1867c478bd9Sstevel@tonic-gate 1877c478bd9Sstevel@tonic-gate for (cnt = 0; cnt < ap->ap_gbadcnt; cnt++) { 1887c478bd9Sstevel@tonic-gate badsec = (ap->ap_gbadp)[cnt].bad_start; 189*cfcc56e0SMark Logan 1907c478bd9Sstevel@tonic-gate /* if bad sector is within the ATLSCTR partition */ 1917c478bd9Sstevel@tonic-gate if ((badsec >= altsp_srtsec) && (badsec <= altsp_endsec)) { 1927c478bd9Sstevel@tonic-gate if ((ap->ap_memmapp)[badsec - altsp_srtsec] != ALTS_BAD) { 1937c478bd9Sstevel@tonic-gate if ((badsec >= altsp_srtsec) && (badsec <= (altsp_srtsec + 1947c478bd9Sstevel@tonic-gate ap->ap_tbl_secsiz / NBPSCTR - 1))) { 195*cfcc56e0SMark Logan (void) fprintf(stderr, 196*cfcc56e0SMark Logan "Alternate partition information table is bad.\n"); 1977c478bd9Sstevel@tonic-gate exit(53); 1987c478bd9Sstevel@tonic-gate } 1997c478bd9Sstevel@tonic-gate if ((badsec >= altsp_srtsec+ap->ap_tblp->alts_map_base) && 2007c478bd9Sstevel@tonic-gate (badsec <= (altsp_srtsec + ap->ap_tblp->alts_map_base + 2017c478bd9Sstevel@tonic-gate ap->ap_map_sectot - 1))) { 202*cfcc56e0SMark Logan (void) fprintf(stderr, 203*cfcc56e0SMark Logan "Alternate partition map is bad.\n"); 2047c478bd9Sstevel@tonic-gate exit(54); 2057c478bd9Sstevel@tonic-gate } 2067c478bd9Sstevel@tonic-gate if ((badsec >= altsp_srtsec+ap->ap_tblp->alts_ent_base) && 2077c478bd9Sstevel@tonic-gate (badsec <= (altsp_srtsec + ap->ap_tblp->alts_ent_base + 2087c478bd9Sstevel@tonic-gate ap->ap_ent_secsiz / NBPSCTR - 1))) { 209*cfcc56e0SMark Logan (void) fprintf(stderr, 210*cfcc56e0SMark Logan "Alternate partition entry table is bad.\n"); 2117c478bd9Sstevel@tonic-gate exit(55); 2127c478bd9Sstevel@tonic-gate } 2137c478bd9Sstevel@tonic-gate (ap->ap_memmapp)[badsec - altsp_srtsec] = ALTS_BAD; 214*cfcc56e0SMark Logan (ap->ap_gbadp)[cnt].bad_start = (uint32_t)ALTS_ENT_EMPTY; 2157c478bd9Sstevel@tonic-gate } else { 2167c478bd9Sstevel@tonic-gate status = chk_bad_altsctr(badsec); 217*cfcc56e0SMark Logan (ap->ap_gbadp)[cnt].bad_start = (uint32_t)ALTS_ENT_EMPTY; 2187c478bd9Sstevel@tonic-gate } 2197c478bd9Sstevel@tonic-gate } else { 2207c478bd9Sstevel@tonic-gate /* 2217c478bd9Sstevel@tonic-gate * binary search for bad sector in the alts entry table 2227c478bd9Sstevel@tonic-gate */ 2237c478bd9Sstevel@tonic-gate status = ent_bsearch(ap->ap_entp, ap->ap_tblp->alts_ent_used, 2247c478bd9Sstevel@tonic-gate &((ap->ap_gbadp)[cnt])); 2257c478bd9Sstevel@tonic-gate /* 2267c478bd9Sstevel@tonic-gate * if the bad sector had already been remapped(found in alts_entry) 2277c478bd9Sstevel@tonic-gate * then ignore the bad sector 2287c478bd9Sstevel@tonic-gate */ 2297c478bd9Sstevel@tonic-gate if (status != -1) { 230*cfcc56e0SMark Logan (ap->ap_gbadp)[cnt].bad_start = (uint32_t)ALTS_ENT_EMPTY; 2317c478bd9Sstevel@tonic-gate } 2327c478bd9Sstevel@tonic-gate } 2337c478bd9Sstevel@tonic-gate } 2347c478bd9Sstevel@tonic-gate 2357c478bd9Sstevel@tonic-gate } 2367c478bd9Sstevel@tonic-gate 2377c478bd9Sstevel@tonic-gate /* 2387c478bd9Sstevel@tonic-gate * initialize the alternate partition tables 2397c478bd9Sstevel@tonic-gate */ 240052b6e8aSbg159949 static void 241052b6e8aSbg159949 init_altsctr(void) 2427c478bd9Sstevel@tonic-gate { 243*cfcc56e0SMark Logan blkaddr_t badsec; 244*cfcc56e0SMark Logan blkaddr_t altsp_srtsec = ap->part.p_start; 245*cfcc56e0SMark Logan blkaddr_t altsp_endsec = ap->part.p_start + ap->part.p_size - 1; 2467c478bd9Sstevel@tonic-gate int cnt; 2477c478bd9Sstevel@tonic-gate 2487c478bd9Sstevel@tonic-gate ap->ap_entp = NULL; 2497c478bd9Sstevel@tonic-gate ap->ap_ent_secsiz = 0; 2507c478bd9Sstevel@tonic-gate ap->ap_tblp->alts_sanity = ALTS_SANITY; 2517c478bd9Sstevel@tonic-gate ap->ap_tblp->alts_version = ALTS_VERSION1; 2527c478bd9Sstevel@tonic-gate ap->ap_tblp->alts_map_len = (ap->part.p_size + 8 - 1) / 8; 2537c478bd9Sstevel@tonic-gate ap->ap_tblp->alts_ent_used = 0; 2547c478bd9Sstevel@tonic-gate ap->ap_tblp->alts_ent_base = 0; 2557c478bd9Sstevel@tonic-gate ap->ap_tblp->alts_ent_end = 0; 2567c478bd9Sstevel@tonic-gate ap->ap_tblp->alts_resv_base = ap->part.p_size - 1; 2577c478bd9Sstevel@tonic-gate for (cnt = 0; cnt < 5; cnt++) 2587c478bd9Sstevel@tonic-gate ap->ap_tblp->alts_pad[cnt] = 0; 2597c478bd9Sstevel@tonic-gate 2607c478bd9Sstevel@tonic-gate for (cnt = 0; cnt < ap->ap_gbadcnt; cnt++) { 2617c478bd9Sstevel@tonic-gate badsec = (ap->ap_gbadp)[cnt].bad_start; 2627c478bd9Sstevel@tonic-gate if ((badsec >= altsp_srtsec) && (badsec <= altsp_endsec)) { 2637c478bd9Sstevel@tonic-gate if (badsec == altsp_srtsec) { 264*cfcc56e0SMark Logan (void) fprintf(stderr, 265*cfcc56e0SMark Logan "First sector of alternate partition is bad.\n"); 2667c478bd9Sstevel@tonic-gate exit(56); 2677c478bd9Sstevel@tonic-gate } 2687c478bd9Sstevel@tonic-gate (ap->ap_memmapp)[badsec - altsp_srtsec] = ALTS_BAD; 269*cfcc56e0SMark Logan (ap->ap_gbadp)[cnt].bad_start = (uint32_t)ALTS_ENT_EMPTY; 2707c478bd9Sstevel@tonic-gate } 2717c478bd9Sstevel@tonic-gate } 2727c478bd9Sstevel@tonic-gate 2737c478bd9Sstevel@tonic-gate /* allocate the alts_map on disk skipping possible bad sectors */ 2747c478bd9Sstevel@tonic-gate ap->ap_tblp->alts_map_base = 2757c478bd9Sstevel@tonic-gate altsmap_alloc(ap->ap_tbl_secsiz / NBPSCTR, 2767c478bd9Sstevel@tonic-gate ap->part.p_size, ap->ap_map_sectot, ALTS_MAP_UP); 2777c478bd9Sstevel@tonic-gate if (ap->ap_tblp->alts_map_base == NULL) { 2787c478bd9Sstevel@tonic-gate perror("Unable to allocate alternate map on disk: "); 2797c478bd9Sstevel@tonic-gate exit(57); 2807c478bd9Sstevel@tonic-gate } 2817c478bd9Sstevel@tonic-gate 2827c478bd9Sstevel@tonic-gate } 2837c478bd9Sstevel@tonic-gate 2847c478bd9Sstevel@tonic-gate 2857c478bd9Sstevel@tonic-gate /* 2867c478bd9Sstevel@tonic-gate * read the alternate partition tables from disk 2877c478bd9Sstevel@tonic-gate */ 2887c478bd9Sstevel@tonic-gate int 2897c478bd9Sstevel@tonic-gate get_altsctr(badok) 2907c478bd9Sstevel@tonic-gate int badok; 2917c478bd9Sstevel@tonic-gate { 2927c478bd9Sstevel@tonic-gate /* get alts partition table info */ 2937c478bd9Sstevel@tonic-gate if (absdsk_io(alts_fd, 0, (char *)ap->ap_tblp, 2947c478bd9Sstevel@tonic-gate ap->ap_tbl_secsiz, CMD_READ) == FAILURE) { 2957c478bd9Sstevel@tonic-gate if (badok) 2967c478bd9Sstevel@tonic-gate return(FAILURE); 2977c478bd9Sstevel@tonic-gate perror("Unable to read alternate sector partition: "); 2987c478bd9Sstevel@tonic-gate exit(58); 2997c478bd9Sstevel@tonic-gate } 3007c478bd9Sstevel@tonic-gate if (ap->ap_tblp->alts_sanity != ALTS_SANITY) { 3017c478bd9Sstevel@tonic-gate if (badok) 3027c478bd9Sstevel@tonic-gate return(FAILURE); 303*cfcc56e0SMark Logan (void) fprintf(stderr, "Bad alternate sector magic number.\n"); 3047c478bd9Sstevel@tonic-gate exit(69); 3057c478bd9Sstevel@tonic-gate } 3067c478bd9Sstevel@tonic-gate 3077c478bd9Sstevel@tonic-gate /* get the alts map */ 3087c478bd9Sstevel@tonic-gate if (absdsk_io(alts_fd, ap->ap_tblp->alts_map_base, 3097c478bd9Sstevel@tonic-gate (char *)ap->ap_mapp, ap->ap_map_secsiz, CMD_READ) == FAILURE) { 3107c478bd9Sstevel@tonic-gate if (badok) 3117c478bd9Sstevel@tonic-gate return(FAILURE); 3127c478bd9Sstevel@tonic-gate perror("Unable to read alternate sector partition map: "); 3137c478bd9Sstevel@tonic-gate exit(59); 3147c478bd9Sstevel@tonic-gate } 3157c478bd9Sstevel@tonic-gate 3167c478bd9Sstevel@tonic-gate /* transform the disk image bit-map to incore char map */ 3177c478bd9Sstevel@tonic-gate expand_map(); 3187c478bd9Sstevel@tonic-gate 3197c478bd9Sstevel@tonic-gate if (ap->ap_tblp->alts_ent_used == 0) { 3207c478bd9Sstevel@tonic-gate ap->ap_entp = NULL; 3217c478bd9Sstevel@tonic-gate ap->ap_ent_secsiz = 0; 3227c478bd9Sstevel@tonic-gate } else { 3237c478bd9Sstevel@tonic-gate ap->ap_ent_secsiz = byte_to_secsiz( 3247c478bd9Sstevel@tonic-gate (ap->ap_tblp->alts_ent_used*ALTS_ENT_SIZE),NBPSCTR); 325*cfcc56e0SMark Logan if ((ap->ap_entp = 326*cfcc56e0SMark Logan (struct alts_ent *)malloc(ap->ap_ent_secsiz)) == NULL) { 3277c478bd9Sstevel@tonic-gate if (badok) 3287c478bd9Sstevel@tonic-gate return(FAILURE); 329*cfcc56e0SMark Logan (void) fprintf(stderr, 330*cfcc56e0SMark Logan "Unable to malloc alternate sector entry table.\n"); 3317c478bd9Sstevel@tonic-gate exit(60); 3327c478bd9Sstevel@tonic-gate } 3337c478bd9Sstevel@tonic-gate 3347c478bd9Sstevel@tonic-gate if (absdsk_io(alts_fd, ap->ap_tblp->alts_ent_base, 3357c478bd9Sstevel@tonic-gate (char *)ap->ap_entp, ap->ap_ent_secsiz, 3367c478bd9Sstevel@tonic-gate CMD_READ) ==FAILURE){ 3377c478bd9Sstevel@tonic-gate if (badok) 3387c478bd9Sstevel@tonic-gate return(FAILURE); 3397c478bd9Sstevel@tonic-gate perror("Unable to read alternate sector entry table: "); 3407c478bd9Sstevel@tonic-gate exit(61); 3417c478bd9Sstevel@tonic-gate } 3427c478bd9Sstevel@tonic-gate } 3437c478bd9Sstevel@tonic-gate return(SUCCESS); 3447c478bd9Sstevel@tonic-gate } 3457c478bd9Sstevel@tonic-gate 3467c478bd9Sstevel@tonic-gate 3477c478bd9Sstevel@tonic-gate /* 3487c478bd9Sstevel@tonic-gate * update the new alternate partition tables on disk 3497c478bd9Sstevel@tonic-gate */ 350052b6e8aSbg159949 void 351052b6e8aSbg159949 wr_altsctr(void) 3527c478bd9Sstevel@tonic-gate { 3537c478bd9Sstevel@tonic-gate if (ap->ap_tblp == NULL) 3547c478bd9Sstevel@tonic-gate return; 355052b6e8aSbg159949 if (absdsk_io(alts_fd, 0, (char *)ap->ap_tblp, 3567c478bd9Sstevel@tonic-gate ap->ap_tbl_secsiz, CMD_WRITE) == FAILURE) { 3577c478bd9Sstevel@tonic-gate perror("Unable to write alternate sector partition: "); 3587c478bd9Sstevel@tonic-gate exit(62); 3597c478bd9Sstevel@tonic-gate } 3607c478bd9Sstevel@tonic-gate 3617c478bd9Sstevel@tonic-gate if (absdsk_io(alts_fd, ap->ap_tblp->alts_map_base, 362052b6e8aSbg159949 (char *)ap->ap_mapp, ap->ap_map_secsiz, CMD_WRITE) == FAILURE) { 3637c478bd9Sstevel@tonic-gate perror("Unable to write alternate sector partition map: "); 3647c478bd9Sstevel@tonic-gate exit(63); 3657c478bd9Sstevel@tonic-gate } 3667c478bd9Sstevel@tonic-gate 3677c478bd9Sstevel@tonic-gate if (ap->ap_tblp->alts_ent_used != 0) { 3687c478bd9Sstevel@tonic-gate if (absdsk_io(alts_fd, ap->ap_tblp->alts_ent_base, 3697c478bd9Sstevel@tonic-gate (char *)ap->ap_entp, ap->ap_ent_secsiz, 3707c478bd9Sstevel@tonic-gate CMD_WRITE) == FAILURE) { 3717c478bd9Sstevel@tonic-gate perror("Unable to write alternate sector entry table: "); 3727c478bd9Sstevel@tonic-gate exit(64); 3737c478bd9Sstevel@tonic-gate } 3747c478bd9Sstevel@tonic-gate } 3757c478bd9Sstevel@tonic-gate } 3767c478bd9Sstevel@tonic-gate 3777c478bd9Sstevel@tonic-gate 3787c478bd9Sstevel@tonic-gate /* 3797c478bd9Sstevel@tonic-gate * get a list of bad sector 3807c478bd9Sstevel@tonic-gate */ 381052b6e8aSbg159949 static void 382052b6e8aSbg159949 get_badsec(void) 3837c478bd9Sstevel@tonic-gate { 3847c478bd9Sstevel@tonic-gate int cnt; 3857c478bd9Sstevel@tonic-gate struct badsec_lst *blc_p; 386*cfcc56e0SMark Logan blkaddr_t curbad; 387*cfcc56e0SMark Logan blkaddr_t maxsec = (blkaddr_t)dkg.dkg_nhead * 388*cfcc56e0SMark Logan dkg.dkg_ncyl * dkg.dkg_nsect; 3897c478bd9Sstevel@tonic-gate struct alts_ent *growbadp; 3907c478bd9Sstevel@tonic-gate int i; 3917c478bd9Sstevel@tonic-gate 3927c478bd9Sstevel@tonic-gate cnt = count_badsec(); 3937c478bd9Sstevel@tonic-gate if (!cnt) { 3947c478bd9Sstevel@tonic-gate ap->ap_gbadp = NULL; 3957c478bd9Sstevel@tonic-gate ap->ap_gbadcnt = 0; 396*cfcc56e0SMark Logan } else { 3977c478bd9Sstevel@tonic-gate ap->ap_gbadp = (struct alts_ent *)malloc(cnt*ALTS_ENT_SIZE); 398*cfcc56e0SMark Logan (void) memset(ap->ap_gbadp,0,cnt*ALTS_ENT_SIZE); 3997c478bd9Sstevel@tonic-gate 4007c478bd9Sstevel@tonic-gate for (growbadp = ap->ap_gbadp, cnt=0, blc_p=badsl_chain; 4017c478bd9Sstevel@tonic-gate blc_p; blc_p=blc_p->bl_nxt) { 4027c478bd9Sstevel@tonic-gate for (i=0; i<blc_p->bl_cnt; i++) { 4037c478bd9Sstevel@tonic-gate curbad = blc_p->bl_sec[i]; 404*cfcc56e0SMark Logan if (curbad < (blkaddr_t)dkg.dkg_nsect) { 405*cfcc56e0SMark Logan (void) fprintf(stderr, 406*cfcc56e0SMark Logan "Ignoring bad sector %ld which is in first" 407*cfcc56e0SMark Logan " track of the drive.\n", curbad); 4087c478bd9Sstevel@tonic-gate continue; 4097c478bd9Sstevel@tonic-gate } 4107c478bd9Sstevel@tonic-gate if (curbad >= maxsec) { 411*cfcc56e0SMark Logan (void) fprintf(stderr, 412*cfcc56e0SMark Logan "Ignoring bad sector %ld which is past" 413*cfcc56e0SMark Logan " the end of the drive.\n", curbad); 4147c478bd9Sstevel@tonic-gate continue; 4157c478bd9Sstevel@tonic-gate } 4167c478bd9Sstevel@tonic-gate growbadp[cnt].bad_start = curbad; 4177c478bd9Sstevel@tonic-gate growbadp[cnt].bad_end = curbad; 4187c478bd9Sstevel@tonic-gate cnt++; 4197c478bd9Sstevel@tonic-gate } 4207c478bd9Sstevel@tonic-gate } 4217c478bd9Sstevel@tonic-gate } 4227c478bd9Sstevel@tonic-gate ap->ap_gbadcnt = cnt; 4237c478bd9Sstevel@tonic-gate } 4247c478bd9Sstevel@tonic-gate 4257c478bd9Sstevel@tonic-gate /* 4267c478bd9Sstevel@tonic-gate * count number of bad sector on list 4277c478bd9Sstevel@tonic-gate * merging the bad sector list from surface analysis and the 4287c478bd9Sstevel@tonic-gate * one given through the command line 4297c478bd9Sstevel@tonic-gate */ 430052b6e8aSbg159949 static int 431052b6e8aSbg159949 count_badsec(void) 4327c478bd9Sstevel@tonic-gate { 4337c478bd9Sstevel@tonic-gate 4347c478bd9Sstevel@tonic-gate struct badsec_lst *blc_p; 4357c478bd9Sstevel@tonic-gate 4367c478bd9Sstevel@tonic-gate if (!badsl_chain) 4377c478bd9Sstevel@tonic-gate badsl_chain = gbadsl_chain; 4387c478bd9Sstevel@tonic-gate else { 4397c478bd9Sstevel@tonic-gate for (blc_p = badsl_chain; blc_p->bl_nxt; blc_p = blc_p->bl_nxt) 4407c478bd9Sstevel@tonic-gate ; 4417c478bd9Sstevel@tonic-gate blc_p->bl_nxt = gbadsl_chain; 4427c478bd9Sstevel@tonic-gate } 4437c478bd9Sstevel@tonic-gate 4447c478bd9Sstevel@tonic-gate badsl_chain_cnt += gbadsl_chain_cnt; 4457c478bd9Sstevel@tonic-gate return(badsl_chain_cnt); 4467c478bd9Sstevel@tonic-gate } 4477c478bd9Sstevel@tonic-gate 4487c478bd9Sstevel@tonic-gate 4497c478bd9Sstevel@tonic-gate /* 4507c478bd9Sstevel@tonic-gate * generate alternate entry table by merging the existing and 4517c478bd9Sstevel@tonic-gate * the new entry list. 4527c478bd9Sstevel@tonic-gate */ 453052b6e8aSbg159949 static void 454052b6e8aSbg159949 gen_alts_ent(void) 455052b6e8aSbg159949 { 456*cfcc56e0SMark Logan uint_t ent_used; 4577c478bd9Sstevel@tonic-gate struct alts_ent *entp; 4587c478bd9Sstevel@tonic-gate 4597c478bd9Sstevel@tonic-gate if (ap->ap_gbadcnt == 0) 4607c478bd9Sstevel@tonic-gate return; 4617c478bd9Sstevel@tonic-gate 4627c478bd9Sstevel@tonic-gate ent_used = ap->ap_tblp->alts_ent_used + ap->ap_gbadcnt; 4637c478bd9Sstevel@tonic-gate ap->ap_ent_secsiz = byte_to_secsiz(ent_used*ALTS_ENT_SIZE,NBPSCTR); 4647c478bd9Sstevel@tonic-gate entp=(struct alts_ent *) malloc (ap->ap_ent_secsiz); 4657c478bd9Sstevel@tonic-gate ent_used = ent_merge(entp, ap->ap_entp, ap->ap_tblp->alts_ent_used, 4667c478bd9Sstevel@tonic-gate ap->ap_gbadp, ap->ap_gbadcnt); 4677c478bd9Sstevel@tonic-gate if (ap->ap_entp) 4687c478bd9Sstevel@tonic-gate free(ap->ap_entp); 4697c478bd9Sstevel@tonic-gate if (ap->ap_gbadp) 4707c478bd9Sstevel@tonic-gate free(ap->ap_gbadp); 4717c478bd9Sstevel@tonic-gate ap->ap_entp = entp; 4727c478bd9Sstevel@tonic-gate ap->ap_ent_secsiz = byte_to_secsiz(ent_used*ALTS_ENT_SIZE, NBPSCTR); 4737c478bd9Sstevel@tonic-gate ap->ap_tblp->alts_ent_used = ent_used; 4747c478bd9Sstevel@tonic-gate ap->ap_gbadp = NULL; 4757c478bd9Sstevel@tonic-gate ap->ap_gbadcnt = 0; 4767c478bd9Sstevel@tonic-gate 4777c478bd9Sstevel@tonic-gate /* assign alternate sectors to the bad sectors */ 4787c478bd9Sstevel@tonic-gate assign_altsctr(); 4797c478bd9Sstevel@tonic-gate 4807c478bd9Sstevel@tonic-gate /* allocate the alts_entry on disk skipping possible bad sectors */ 4817c478bd9Sstevel@tonic-gate ap->ap_tblp->alts_ent_base = 4827c478bd9Sstevel@tonic-gate altsmap_alloc(ap->ap_tblp->alts_map_base + ap->ap_map_sectot, 4837c478bd9Sstevel@tonic-gate ap->part.p_size, 4847c478bd9Sstevel@tonic-gate ap->ap_ent_secsiz / NBPSCTR, ALTS_MAP_UP); 4857c478bd9Sstevel@tonic-gate if (ap->ap_tblp->alts_ent_base == NULL) { 4867c478bd9Sstevel@tonic-gate perror("Unable to allocate alternate entry table on disk: "); 4877c478bd9Sstevel@tonic-gate exit(65); 4887c478bd9Sstevel@tonic-gate } 4897c478bd9Sstevel@tonic-gate 4907c478bd9Sstevel@tonic-gate ap->ap_tblp->alts_ent_end = ap->ap_tblp->alts_ent_base + 4917c478bd9Sstevel@tonic-gate (ap->ap_ent_secsiz / NBPSCTR) - 1; 4927c478bd9Sstevel@tonic-gate } 4937c478bd9Sstevel@tonic-gate 4947c478bd9Sstevel@tonic-gate 4957c478bd9Sstevel@tonic-gate /* 4967c478bd9Sstevel@tonic-gate * assign alternate sectors for bad sector mapping 4977c478bd9Sstevel@tonic-gate */ 498052b6e8aSbg159949 static void 499052b6e8aSbg159949 assign_altsctr(void) 5007c478bd9Sstevel@tonic-gate { 501*cfcc56e0SMark Logan uint_t i; 502*cfcc56e0SMark Logan uint_t j; 503*cfcc56e0SMark Logan blkaddr_t alts_ind; 504*cfcc56e0SMark Logan uint_t cluster; 5057c478bd9Sstevel@tonic-gate 5067c478bd9Sstevel@tonic-gate for (i = 0; i < ap->ap_tblp->alts_ent_used; i++) { 507*cfcc56e0SMark Logan if ((ap->ap_entp)[i].bad_start == (uint32_t)ALTS_ENT_EMPTY) 5087c478bd9Sstevel@tonic-gate continue; 5097c478bd9Sstevel@tonic-gate if ((ap->ap_entp)[i].good_start != 0) 5107c478bd9Sstevel@tonic-gate continue; 5117c478bd9Sstevel@tonic-gate cluster = (ap->ap_entp)[i].bad_end-(ap->ap_entp)[i].bad_start +1; 5127c478bd9Sstevel@tonic-gate alts_ind = 5137c478bd9Sstevel@tonic-gate altsmap_alloc(ap->part.p_size-1, ap->ap_tblp->alts_map_base + 5147c478bd9Sstevel@tonic-gate ap->ap_map_sectot - 1, cluster, ALTS_MAP_DOWN); 5157c478bd9Sstevel@tonic-gate if (alts_ind == NULL) { 516*cfcc56e0SMark Logan (void) fprintf(stderr, 517*cfcc56e0SMark Logan "Unable to allocate alternates for bad starting" 518*cfcc56e0SMark Logan " sector %u.\n", (ap->ap_entp)[i].bad_start); 5197c478bd9Sstevel@tonic-gate exit(65); 5207c478bd9Sstevel@tonic-gate } 5217c478bd9Sstevel@tonic-gate alts_ind = alts_ind - cluster + 1; 5227c478bd9Sstevel@tonic-gate (ap->ap_entp)[i].good_start = alts_ind + ap->part.p_start; 5237c478bd9Sstevel@tonic-gate for (j = 0; j < cluster; j++) { 5247c478bd9Sstevel@tonic-gate (ap->ap_memmapp)[alts_ind+j] = ALTS_BAD; 5257c478bd9Sstevel@tonic-gate } 5267c478bd9Sstevel@tonic-gate 5277c478bd9Sstevel@tonic-gate } 5287c478bd9Sstevel@tonic-gate 5297c478bd9Sstevel@tonic-gate } 5307c478bd9Sstevel@tonic-gate 5317c478bd9Sstevel@tonic-gate /* 5327c478bd9Sstevel@tonic-gate * transform the disk image alts bit map to incore char map 5337c478bd9Sstevel@tonic-gate */ 534052b6e8aSbg159949 static void 535052b6e8aSbg159949 expand_map(void) 5367c478bd9Sstevel@tonic-gate { 5377c478bd9Sstevel@tonic-gate int i; 5387c478bd9Sstevel@tonic-gate 5397c478bd9Sstevel@tonic-gate for (i = 0; i < ap->part.p_size; i++) { 5407c478bd9Sstevel@tonic-gate (ap->ap_memmapp)[i] = altsmap_getbit(i); 5417c478bd9Sstevel@tonic-gate } 5427c478bd9Sstevel@tonic-gate } 5437c478bd9Sstevel@tonic-gate 5447c478bd9Sstevel@tonic-gate /* 5457c478bd9Sstevel@tonic-gate * transform the incore alts char map to the disk image bit map 5467c478bd9Sstevel@tonic-gate */ 547052b6e8aSbg159949 static void 548052b6e8aSbg159949 compress_map(void) 5497c478bd9Sstevel@tonic-gate { 5507c478bd9Sstevel@tonic-gate 5517c478bd9Sstevel@tonic-gate int i; 5527c478bd9Sstevel@tonic-gate int bytesz; 5537c478bd9Sstevel@tonic-gate char mask = 0; 5547c478bd9Sstevel@tonic-gate int maplen = 0; 5557c478bd9Sstevel@tonic-gate 5567c478bd9Sstevel@tonic-gate for (i = 0, bytesz = 7; i < ap->part.p_size; i++) { 5577c478bd9Sstevel@tonic-gate mask |= ((ap->ap_memmapp)[i] << bytesz--); 5587c478bd9Sstevel@tonic-gate if (bytesz < 0) { 5597c478bd9Sstevel@tonic-gate (ap->ap_mapp)[maplen++] = mask; 5607c478bd9Sstevel@tonic-gate bytesz = 7; 5617c478bd9Sstevel@tonic-gate mask = 0; 5627c478bd9Sstevel@tonic-gate } 5637c478bd9Sstevel@tonic-gate } 5647c478bd9Sstevel@tonic-gate /* 5657c478bd9Sstevel@tonic-gate * if partition size != multiple number of bytes 5667c478bd9Sstevel@tonic-gate * then record the last partial byte 5677c478bd9Sstevel@tonic-gate */ 5687c478bd9Sstevel@tonic-gate if (bytesz != 7) 5697c478bd9Sstevel@tonic-gate (ap->ap_mapp)[maplen] = mask; 5707c478bd9Sstevel@tonic-gate 5717c478bd9Sstevel@tonic-gate } 5727c478bd9Sstevel@tonic-gate 5737c478bd9Sstevel@tonic-gate /* 5747c478bd9Sstevel@tonic-gate * given a bad sector number, search in the alts bit map 5757c478bd9Sstevel@tonic-gate * and identify the sector as good or bad 5767c478bd9Sstevel@tonic-gate */ 577052b6e8aSbg159949 static int 578*cfcc56e0SMark Logan altsmap_getbit(blkaddr_t badsec) 5797c478bd9Sstevel@tonic-gate { 580*cfcc56e0SMark Logan uint_t slot = badsec / 8; 581*cfcc56e0SMark Logan uint_t field = badsec % 8; 582*cfcc56e0SMark Logan uchar_t mask; 5837c478bd9Sstevel@tonic-gate 5847c478bd9Sstevel@tonic-gate mask = ALTS_BAD<<7; 5857c478bd9Sstevel@tonic-gate mask >>= field; 5867c478bd9Sstevel@tonic-gate if ((ap->ap_mapp)[slot] & mask) 5877c478bd9Sstevel@tonic-gate return(ALTS_BAD); 5887c478bd9Sstevel@tonic-gate return(ALTS_GOOD); 5897c478bd9Sstevel@tonic-gate } 5907c478bd9Sstevel@tonic-gate 5917c478bd9Sstevel@tonic-gate 5927c478bd9Sstevel@tonic-gate /* 5937c478bd9Sstevel@tonic-gate * allocate a range of sectors from the alternate partition 5947c478bd9Sstevel@tonic-gate */ 595*cfcc56e0SMark Logan static blkaddr_t 596*cfcc56e0SMark Logan altsmap_alloc(blkaddr_t srt_ind, blkaddr_t end_ind, int cnt, int dir) 5977c478bd9Sstevel@tonic-gate { 598*cfcc56e0SMark Logan blkaddr_t i; 599*cfcc56e0SMark Logan blkaddr_t total; 600*cfcc56e0SMark Logan blkaddr_t first_ind; 6017c478bd9Sstevel@tonic-gate 602*cfcc56e0SMark Logan for (i = srt_ind, first_ind = srt_ind, total = 0; 603*cfcc56e0SMark Logan i != end_ind; i += dir) { 6047c478bd9Sstevel@tonic-gate if ((ap->ap_memmapp)[i] == ALTS_BAD) { 6057c478bd9Sstevel@tonic-gate total = 0; 6067c478bd9Sstevel@tonic-gate first_ind = i + dir; 6077c478bd9Sstevel@tonic-gate continue; 6087c478bd9Sstevel@tonic-gate } 6097c478bd9Sstevel@tonic-gate total++; 6107c478bd9Sstevel@tonic-gate if (total == cnt) 6117c478bd9Sstevel@tonic-gate return(first_ind); 6127c478bd9Sstevel@tonic-gate 6137c478bd9Sstevel@tonic-gate } 614052b6e8aSbg159949 return(0); 6157c478bd9Sstevel@tonic-gate } 6167c478bd9Sstevel@tonic-gate 6177c478bd9Sstevel@tonic-gate 6187c478bd9Sstevel@tonic-gate 6197c478bd9Sstevel@tonic-gate /* 6207c478bd9Sstevel@tonic-gate * bubble sort the entry table into ascending order 6217c478bd9Sstevel@tonic-gate */ 622052b6e8aSbg159949 static void 623052b6e8aSbg159949 ent_sort(struct alts_ent buf[], int cnt) 6247c478bd9Sstevel@tonic-gate { 6257c478bd9Sstevel@tonic-gate struct alts_ent temp; 6267c478bd9Sstevel@tonic-gate int flag; 6277c478bd9Sstevel@tonic-gate int i, j; 6287c478bd9Sstevel@tonic-gate 6297c478bd9Sstevel@tonic-gate for (i = 0; i < cnt-1; i++) { 6307c478bd9Sstevel@tonic-gate temp = buf[cnt-1]; 6317c478bd9Sstevel@tonic-gate flag = 1; 6327c478bd9Sstevel@tonic-gate 6337c478bd9Sstevel@tonic-gate for (j = cnt-1; j > i; j--) { 6347c478bd9Sstevel@tonic-gate if (buf[j-1].bad_start < temp.bad_start) { 6357c478bd9Sstevel@tonic-gate buf[j] = temp; 6367c478bd9Sstevel@tonic-gate temp = buf[j-1]; 6377c478bd9Sstevel@tonic-gate } else { 6387c478bd9Sstevel@tonic-gate buf[j] = buf[j-1]; 6397c478bd9Sstevel@tonic-gate flag = 0; 6407c478bd9Sstevel@tonic-gate } 6417c478bd9Sstevel@tonic-gate } 6427c478bd9Sstevel@tonic-gate buf[i] = temp; 6437c478bd9Sstevel@tonic-gate if (flag) break; 6447c478bd9Sstevel@tonic-gate } 6457c478bd9Sstevel@tonic-gate 6467c478bd9Sstevel@tonic-gate } 6477c478bd9Sstevel@tonic-gate 6487c478bd9Sstevel@tonic-gate 6497c478bd9Sstevel@tonic-gate /* 6507c478bd9Sstevel@tonic-gate * compress all the contiguous bad sectors into a single entry 6517c478bd9Sstevel@tonic-gate * in the entry table. The entry table must be sorted into ascending 6527c478bd9Sstevel@tonic-gate * before the compression. 6537c478bd9Sstevel@tonic-gate */ 654052b6e8aSbg159949 static void 655052b6e8aSbg159949 ent_compress(struct alts_ent buf[], int cnt) 6567c478bd9Sstevel@tonic-gate { 6577c478bd9Sstevel@tonic-gate int keyp; 6587c478bd9Sstevel@tonic-gate int movp; 6597c478bd9Sstevel@tonic-gate int i; 6607c478bd9Sstevel@tonic-gate 6617c478bd9Sstevel@tonic-gate for (i = 0; i < cnt; i++) { 662*cfcc56e0SMark Logan if (buf[i].bad_start == (uint32_t)ALTS_ENT_EMPTY) 6637c478bd9Sstevel@tonic-gate continue; 6647c478bd9Sstevel@tonic-gate for (keyp = i, movp = i+1; movp < cnt; movp++) { 665*cfcc56e0SMark Logan if (buf[movp].bad_start == (uint32_t)ALTS_ENT_EMPTY) 6667c478bd9Sstevel@tonic-gate continue; 6677c478bd9Sstevel@tonic-gate if (buf[keyp].bad_end+1 != buf[movp].bad_start) 6687c478bd9Sstevel@tonic-gate break; 6697c478bd9Sstevel@tonic-gate buf[keyp].bad_end++; 670*cfcc56e0SMark Logan buf[movp].bad_start = (uint32_t)ALTS_ENT_EMPTY; 6717c478bd9Sstevel@tonic-gate } 6727c478bd9Sstevel@tonic-gate if (movp == cnt) break; 6737c478bd9Sstevel@tonic-gate } 6747c478bd9Sstevel@tonic-gate } 6757c478bd9Sstevel@tonic-gate 6767c478bd9Sstevel@tonic-gate 6777c478bd9Sstevel@tonic-gate /* 6787c478bd9Sstevel@tonic-gate * merging two entry tables into a single table. In addition, 6797c478bd9Sstevel@tonic-gate * all empty slots in the entry table will be removed. 6807c478bd9Sstevel@tonic-gate */ 681052b6e8aSbg159949 static int 682052b6e8aSbg159949 ent_merge( 683052b6e8aSbg159949 struct alts_ent buf[], 684052b6e8aSbg159949 struct alts_ent list1[], 685052b6e8aSbg159949 int lcnt1, 686052b6e8aSbg159949 struct alts_ent list2[], 687052b6e8aSbg159949 int lcnt2) 6887c478bd9Sstevel@tonic-gate { 6897c478bd9Sstevel@tonic-gate int i; 6907c478bd9Sstevel@tonic-gate int j1, j2; 6917c478bd9Sstevel@tonic-gate 6927c478bd9Sstevel@tonic-gate for (i = 0, j1 = 0, j2 = 0; j1 < lcnt1 && j2 < lcnt2; ) { 693*cfcc56e0SMark Logan if (list1[j1].bad_start == (uint32_t)ALTS_ENT_EMPTY) { 6947c478bd9Sstevel@tonic-gate j1++; 6957c478bd9Sstevel@tonic-gate continue; 6967c478bd9Sstevel@tonic-gate } 697*cfcc56e0SMark Logan if (list2[j2].bad_start == (uint32_t)ALTS_ENT_EMPTY) { 6987c478bd9Sstevel@tonic-gate j2++; 6997c478bd9Sstevel@tonic-gate continue; 7007c478bd9Sstevel@tonic-gate } 7017c478bd9Sstevel@tonic-gate if (list1[j1].bad_start < list2[j2].bad_start) 7027c478bd9Sstevel@tonic-gate buf[i++] = list1[j1++]; 7037c478bd9Sstevel@tonic-gate else 7047c478bd9Sstevel@tonic-gate buf[i++] = list2[j2++]; 7057c478bd9Sstevel@tonic-gate } 7067c478bd9Sstevel@tonic-gate for (; j1 < lcnt1; j1++) { 707*cfcc56e0SMark Logan if (list1[j1].bad_start == (uint32_t)ALTS_ENT_EMPTY) 7087c478bd9Sstevel@tonic-gate continue; 7097c478bd9Sstevel@tonic-gate buf[i++] = list1[j1]; 7107c478bd9Sstevel@tonic-gate } 7117c478bd9Sstevel@tonic-gate for (; j2 < lcnt2; j2++) { 712*cfcc56e0SMark Logan if (list2[j2].bad_start == (uint32_t)ALTS_ENT_EMPTY) 7137c478bd9Sstevel@tonic-gate continue; 7147c478bd9Sstevel@tonic-gate buf[i++] = list2[j2]; 7157c478bd9Sstevel@tonic-gate } 7167c478bd9Sstevel@tonic-gate return (i); 7177c478bd9Sstevel@tonic-gate } 7187c478bd9Sstevel@tonic-gate 7197c478bd9Sstevel@tonic-gate 7207c478bd9Sstevel@tonic-gate /* 7217c478bd9Sstevel@tonic-gate * binary search for bad sector in the alternate entry table 7227c478bd9Sstevel@tonic-gate */ 723052b6e8aSbg159949 static int 724052b6e8aSbg159949 ent_bsearch(struct alts_ent buf[], int cnt, struct alts_ent *key) 7257c478bd9Sstevel@tonic-gate { 7267c478bd9Sstevel@tonic-gate int i; 7277c478bd9Sstevel@tonic-gate int ind; 7287c478bd9Sstevel@tonic-gate int interval; 7297c478bd9Sstevel@tonic-gate int mystatus = -1; 7307c478bd9Sstevel@tonic-gate 731*cfcc56e0SMark Logan if (!cnt) 732*cfcc56e0SMark Logan return(mystatus); 7337c478bd9Sstevel@tonic-gate 7347c478bd9Sstevel@tonic-gate for (i = 1; i <= cnt; i <<= 1) 7357c478bd9Sstevel@tonic-gate ind = i; 7367c478bd9Sstevel@tonic-gate 7377c478bd9Sstevel@tonic-gate for (interval = ind; interval; ) { 7387c478bd9Sstevel@tonic-gate /* 7397c478bd9Sstevel@tonic-gate printf("ind= %d, intv= %d; ",ind, interval); 7407c478bd9Sstevel@tonic-gate */ 7417c478bd9Sstevel@tonic-gate if ((key->bad_start >= buf[ind-1].bad_start) && 7427c478bd9Sstevel@tonic-gate (key->bad_start <= buf[ind-1].bad_end)) { 7437c478bd9Sstevel@tonic-gate return(mystatus = ind-1); 7447c478bd9Sstevel@tonic-gate } else { 7457c478bd9Sstevel@tonic-gate interval >>= 1; 7467c478bd9Sstevel@tonic-gate if (!interval) break; 7477c478bd9Sstevel@tonic-gate if (key->bad_start < buf[ind-1].bad_start) { 7487c478bd9Sstevel@tonic-gate ind = ind - interval; 7497c478bd9Sstevel@tonic-gate } else { 7507c478bd9Sstevel@tonic-gate /* if key is larger than the last element then break */ 7517c478bd9Sstevel@tonic-gate if (ind == cnt) break; 7527c478bd9Sstevel@tonic-gate if ((ind+interval) <= cnt) 7537c478bd9Sstevel@tonic-gate ind += interval; 7547c478bd9Sstevel@tonic-gate } 7557c478bd9Sstevel@tonic-gate } 7567c478bd9Sstevel@tonic-gate } 7577c478bd9Sstevel@tonic-gate return(mystatus); 7587c478bd9Sstevel@tonic-gate } 7597c478bd9Sstevel@tonic-gate 7607c478bd9Sstevel@tonic-gate /* 7617c478bd9Sstevel@tonic-gate * check for bad sector in assigned alternate sectors 7627c478bd9Sstevel@tonic-gate */ 763052b6e8aSbg159949 static int 764*cfcc56e0SMark Logan chk_bad_altsctr(blkaddr_t badsec) 7657c478bd9Sstevel@tonic-gate { 7667c478bd9Sstevel@tonic-gate int i; 767*cfcc56e0SMark Logan blkaddr_t numsec; 7687c478bd9Sstevel@tonic-gate int cnt = ap->ap_tblp->alts_ent_used; 769*cfcc56e0SMark Logan /* 770*cfcc56e0SMark Logan * blkaddr_t intv[3]; 771*cfcc56e0SMark Logan */ 7727c478bd9Sstevel@tonic-gate 7737c478bd9Sstevel@tonic-gate for (i = 0; i < cnt; i++) { 7747c478bd9Sstevel@tonic-gate numsec = (ap->ap_entp)[i].bad_end - (ap->ap_entp)[i].bad_start; 7757c478bd9Sstevel@tonic-gate if ((badsec >= (ap->ap_entp)[i].good_start) && 7767c478bd9Sstevel@tonic-gate (badsec <= ((ap->ap_entp)[i].good_start + numsec))) { 777*cfcc56e0SMark Logan (void) fprintf(stderr, "Bad sector %ld is an assigned" 778*cfcc56e0SMark Logan " alternate sector.\n", badsec); 7797c478bd9Sstevel@tonic-gate exit(66); 7807c478bd9Sstevel@tonic-gate /* 781*cfcc56e0SMark Logan * if (!numsec) { 782*cfcc56e0SMark Logan * (ap->ap_entp)[i].good_start = 0; 783*cfcc56e0SMark Logan * return (FAILURE); 784*cfcc56e0SMark Logan * } 785*cfcc56e0SMark Logan * intv[0] = badsec - (ap->ap_entp)[i].good_start; 786*cfcc56e0SMark Logan * intv[1] = 1; 787*cfcc56e0SMark Logan * intv[2] = (ap->ap_entp)[i].good_start + numsec - badsec; 7887c478bd9Sstevel@tonic-gate */ 7897c478bd9Sstevel@tonic-gate } 7907c478bd9Sstevel@tonic-gate } 7917c478bd9Sstevel@tonic-gate /* the bad sector has already been identified as bad */ 792*cfcc56e0SMark Logan return(SUCCESS); 7937c478bd9Sstevel@tonic-gate } 7947c478bd9Sstevel@tonic-gate 7957c478bd9Sstevel@tonic-gate 7967c478bd9Sstevel@tonic-gate /* 7977c478bd9Sstevel@tonic-gate * print_altsec () -- print alternate sector information 7987c478bd9Sstevel@tonic-gate */ 799052b6e8aSbg159949 int 800*cfcc56e0SMark Logan print_altsec(struct extpartition *part) 8017c478bd9Sstevel@tonic-gate { 8027c478bd9Sstevel@tonic-gate ap->ap_tblp = NULL; 8037c478bd9Sstevel@tonic-gate ap->ap_flag &= ~ALTS_ADDPART; 8047c478bd9Sstevel@tonic-gate read_altsctr(part, 0); 8057c478bd9Sstevel@tonic-gate print_altsctr(); 8067c478bd9Sstevel@tonic-gate return(SUCCESS); 8077c478bd9Sstevel@tonic-gate } 8087c478bd9Sstevel@tonic-gate 809052b6e8aSbg159949 static void 810052b6e8aSbg159949 print_altsctr(void) 8117c478bd9Sstevel@tonic-gate { 8127c478bd9Sstevel@tonic-gate int i; 8137c478bd9Sstevel@tonic-gate int totalloc; 8147c478bd9Sstevel@tonic-gate int avail; 8157c478bd9Sstevel@tonic-gate 8167c478bd9Sstevel@tonic-gate /* find # of available alternate sectors */ 8177c478bd9Sstevel@tonic-gate for (i=0, totalloc=0; i<ap->part.p_size; i++) { 8187c478bd9Sstevel@tonic-gate if ((ap->ap_memmapp)[i]) 8197c478bd9Sstevel@tonic-gate totalloc++; 8207c478bd9Sstevel@tonic-gate } 8217c478bd9Sstevel@tonic-gate /* 8227c478bd9Sstevel@tonic-gate * available = size of partition - allocated sectors/bad sectors 8237c478bd9Sstevel@tonic-gate * - partition table - partition map 8247c478bd9Sstevel@tonic-gate * - entry table 8257c478bd9Sstevel@tonic-gate */ 8267c478bd9Sstevel@tonic-gate avail = ap->part.p_size - totalloc; 8277c478bd9Sstevel@tonic-gate avail = avail - (ap->ap_tbl_secsiz/NBPSCTR) 8287c478bd9Sstevel@tonic-gate - ap->ap_map_sectot; 8297c478bd9Sstevel@tonic-gate avail = avail-(ap->ap_tblp->alts_ent_end -ap->ap_tblp->alts_ent_base+1); 8307c478bd9Sstevel@tonic-gate if (avail < 0) avail = 0; 8317c478bd9Sstevel@tonic-gate 832*cfcc56e0SMark Logan (void) printf("\nALTERNATE SECTOR/TRACK MAPPING TABLE:\n"); 833*cfcc56e0SMark Logan (void) printf("\nBad Sector Start\tAlternate Sector Start\t\tCount\n"); 8347c478bd9Sstevel@tonic-gate 8357c478bd9Sstevel@tonic-gate for (i=0; i<ap->ap_tblp->alts_ent_used; i++) { 836*cfcc56e0SMark Logan (void) printf("\t%u\t ->\t\t%u\t\t\t %u\n", 8377c478bd9Sstevel@tonic-gate (ap->ap_entp)[i].bad_start, 8387c478bd9Sstevel@tonic-gate (ap->ap_entp)[i].good_start, 8397c478bd9Sstevel@tonic-gate ((ap->ap_entp)[i].bad_end - (ap->ap_entp)[i].bad_start + 1)); 8407c478bd9Sstevel@tonic-gate } 841*cfcc56e0SMark Logan (void) printf("\n %d alternate sector(s) left for allocation.\n", 842*cfcc56e0SMark Logan avail); 8437c478bd9Sstevel@tonic-gate 8447c478bd9Sstevel@tonic-gate } 8457c478bd9Sstevel@tonic-gate 846052b6e8aSbg159949 static int 847*cfcc56e0SMark Logan absdsk_io(int fd, uint_t srtsec, char *bufp, uint_t len, int ioflag) 8487c478bd9Sstevel@tonic-gate { 8497c478bd9Sstevel@tonic-gate int rc; 8507c478bd9Sstevel@tonic-gate 851*cfcc56e0SMark Logan if (llseek (fd, (offset_t)srtsec * NBPSCTR, SEEK_SET) == -1) 8527c478bd9Sstevel@tonic-gate return(FAILURE); 8537c478bd9Sstevel@tonic-gate switch (ioflag) 8547c478bd9Sstevel@tonic-gate { 8557c478bd9Sstevel@tonic-gate case CMD_READ: 8567c478bd9Sstevel@tonic-gate rc = read (fd, bufp, len); 8577c478bd9Sstevel@tonic-gate break; 8587c478bd9Sstevel@tonic-gate case CMD_WRITE: 8597c478bd9Sstevel@tonic-gate rc = write (fd, bufp, len); 8607c478bd9Sstevel@tonic-gate break; 8617c478bd9Sstevel@tonic-gate default: 8627c478bd9Sstevel@tonic-gate break; 8637c478bd9Sstevel@tonic-gate } 8647c478bd9Sstevel@tonic-gate if (rc == -1) 8657c478bd9Sstevel@tonic-gate return(FAILURE); 8667c478bd9Sstevel@tonic-gate return(SUCCESS); 8677c478bd9Sstevel@tonic-gate } 868