1 /* $NetBSD: read.c,v 1.2 2001/02/25 14:32:59 jdc Exp $ */ 2 3 /* 4 * Copyright (c) 1999 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Julian Coleman, Waldi Ravens and Leo Weppelman. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the NetBSD 21 * Foundation, Inc. and its contributors. 22 * 4. Neither the name of The NetBSD Foundation nor the names of its 23 * contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39 #include "privahdi.h" 40 #include <fcntl.h> 41 #ifdef DEBUG 42 #include <stdio.h> 43 #endif 44 #include <stdlib.h> 45 #include <strings.h> 46 #include <unistd.h> 47 #include <sys/dkio.h> 48 #include <sys/ioctl.h> 49 50 /* 51 * Read AHDI partitions from disk. 52 */ 53 int 54 ahdi_readlabel (ptable, diskname, flags) 55 struct ahdi_ptable *ptable; 56 char *diskname; 57 int flags; 58 { 59 int fd, rv; 60 struct disklabel *dl; 61 62 if (!(fd = openraw (diskname, O_RDONLY))) 63 return (-1); 64 65 if ((dl = read_dl (fd)) == NULL) { 66 close (fd); 67 return (-1); 68 } 69 70 if (dl->d_secsize != AHDI_BSIZE) { 71 close (fd); 72 return (-2); 73 } 74 75 if ((rv = check_magic(fd, LABELSECTOR, flags)) < 0) { 76 close (fd); 77 return (rv); 78 } 79 80 bzero ((void *) ptable, sizeof (struct ahdi_ptable)); 81 82 if ((rv = read_rsec (fd, ptable, AHDI_BBLOCK, AHDI_BBLOCK, flags)) 83 < 0) { 84 close (fd); 85 return (rv); 86 } 87 88 if (dl->d_secperunit != ptable->secperunit) { 89 if (flags & AHDI_IGN_SPU) 90 ptable->secperunit = dl->d_secperunit; 91 else { 92 close (fd); 93 return (-6); 94 } 95 } 96 97 ptable->nsectors = dl->d_nsectors; 98 ptable->ntracks = dl->d_ntracks; 99 ptable->ncylinders = dl->d_ncylinders; 100 ptable->secpercyl = dl->d_secpercyl; 101 102 assign_letters (ptable); 103 104 close (fd); 105 return (1); 106 } 107 108 /* 109 * Read AHDI partitions from root sector/auxillary root sector. 110 */ 111 int 112 read_rsec (fd, ptable, rsec, esec, flags) 113 int fd; 114 struct ahdi_ptable *ptable; 115 u_int rsec, esec; 116 int flags; 117 { 118 struct ahdi_part *part, *end; 119 struct ahdi_root *root; 120 u_int16_t cksum, newcksum; 121 int rv; 122 123 if ((root = disk_read (fd, rsec, 1)) == NULL) { 124 return (-1); 125 } 126 127 if (rsec == AHDI_BBLOCK) { 128 end = &root->ar_parts[AHDI_MAXRPD]; 129 if (root->ar_checksum) { 130 cksum = root->ar_checksum; 131 root->ar_checksum = 0; 132 newcksum = ahdi_cksum (root); 133 if ((cksum != newcksum) && !(flags & AHDI_IGN_CKSUM)) { 134 free (root); 135 return (-4); 136 } 137 } 138 ptable->secperunit=root->ar_hdsize; 139 } else 140 end = &root->ar_parts[AHDI_MAXARPD]; 141 for (part = root->ar_parts; part < end; ++part) { 142 #ifdef DEBUG 143 printf ("Found partitions at sector %u:\n", rsec); 144 printf (" flags : %02x\n", part->ap_flg); 145 printf (" id : %c%c%c\n", part->ap_id[0], part->ap_id[1], 146 part->ap_id[2]); 147 printf (" start : %u\n", part->ap_st); 148 printf (" size : %u\n", part->ap_size); 149 #endif 150 if (!(part->ap_flg & 0x01)) { 151 if ((part->ap_id[0] || part->ap_id[1] || 152 part->ap_id[2]) && (flags & AHDI_IGN_EXISTS)) 153 part->ap_flg &= 0x01; 154 else 155 continue; 156 } 157 158 if (AHDI_MKPID (part->ap_id[0], part->ap_id[1], 159 part->ap_id[2]) == AHDI_PID_XGM) { 160 u_int offs = part->ap_st + esec; 161 if ((rv = read_rsec (fd, ptable, offs, 162 esec == AHDI_BBLOCK ? offs : esec, flags)) < 0) { 163 free (root); 164 return (rv); 165 } 166 } else { 167 /* Attempt to check for junk values */ 168 if (((part->ap_st + rsec) > ptable->secperunit || 169 (part->ap_st + rsec + part->ap_size -1) > 170 ptable->secperunit)) { 171 if (flags & AHDI_IGN_EXT) { 172 /* Fake previous partition */ 173 ptable->parts[ptable->nparts].id[0] = 174 part->ap_id[0]; 175 ptable->parts[ptable->nparts].id[1] = 176 part->ap_id[1]; 177 ptable->parts[ptable->nparts].id[2] = 178 part->ap_id[2]; 179 } else { 180 free (root); 181 return (-5); 182 } 183 } 184 ptable->parts[ptable->nparts].flag = part->ap_flg; 185 ptable->parts[ptable->nparts].id[0] = part->ap_id[0]; 186 ptable->parts[ptable->nparts].id[1] = part->ap_id[1]; 187 ptable->parts[ptable->nparts].id[2] = part->ap_id[2]; 188 ptable->parts[ptable->nparts].root = rsec; 189 ptable->parts[ptable->nparts].start = 190 part->ap_st + rsec; 191 ptable->parts[ptable->nparts].size = part->ap_size; 192 ptable->nparts++; 193 } 194 } 195 free (root); 196 if (ptable->nparts || FORCE_AHDI) 197 return (1); 198 else 199 return (-3); 200 } 201 202 /* 203 * Read a sector from the disk. 204 */ 205 void * 206 disk_read (fd, start, count) 207 int fd; 208 u_int start, 209 count; 210 { 211 void *buffer; 212 off_t offset; 213 size_t size; 214 215 216 size = count * DEV_BSIZE; 217 offset = start * DEV_BSIZE; 218 219 if ((buffer = malloc (size)) == NULL) 220 return (NULL); 221 222 if (lseek (fd, offset, SEEK_SET) != offset) { 223 free (buffer); 224 return (NULL); 225 } 226 if (read (fd, buffer, size) != size) { 227 free (buffer); 228 return (NULL); 229 } 230 return (buffer); 231 } 232 233 /* 234 * Assign NetBSD drive letters to partitions 235 */ 236 void 237 assign_letters (ptable) 238 struct ahdi_ptable *ptable; 239 { 240 int i, have_root, pno; 241 u_int32_t pid; 242 243 #define ROOT_PART 0 244 245 have_root = 0; 246 pno = 0; 247 248 for (i = 0; i < ptable->nparts; i++) { 249 while (pno == ROOT_PART || pno == SWAP_PART || pno == RAW_PART) 250 pno++; 251 pid = AHDI_MKPID (ptable->parts[i].id[0], 252 ptable->parts[i].id[1], ptable->parts[i].id[2]); 253 if (!have_root && pid == AHDI_PID_NBD) { 254 ptable->parts[i].letter = ROOT_PART; 255 have_root = 1; 256 } else if (pid == AHDI_PID_SWP) 257 ptable->parts[i].letter = SWAP_PART; 258 else { 259 ptable->parts[i].letter = pno; 260 pno++; 261 } 262 } 263 } 264 265 /* 266 * Read disklabel for disk. 267 */ 268 struct disklabel * 269 read_dl (fd) 270 int fd; 271 { 272 struct disklabel *dl; 273 274 if ((dl = malloc (sizeof (struct disklabel))) == NULL) { 275 return (NULL); 276 } 277 278 if (ioctl (fd, DIOCGDINFO, dl) < 0) { 279 free (dl); 280 return (NULL); 281 } 282 return (dl); 283 } 284