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