Home | History | Annotate | Line # | Download | only in aptck
disklbl.c revision 1.3.44.1
      1  1.3.44.1  lukem /*	$NetBSD: disklbl.c,v 1.3.44.1 2001/08/03 04:11:18 lukem Exp $	*/
      2       1.1    leo 
      3       1.1    leo /*
      4       1.1    leo  * Copyright (c) 1995 Waldi Ravens.
      5       1.1    leo  * All rights reserved.
      6       1.1    leo  *
      7       1.1    leo  * Redistribution and use in source and binary forms, with or without
      8       1.1    leo  * modification, are permitted provided that the following conditions
      9       1.1    leo  * are met:
     10       1.1    leo  * 1. Redistributions of source code must retain the above copyright
     11       1.1    leo  *    notice, this list of conditions and the following disclaimer.
     12       1.1    leo  * 2. Redistributions in binary form must reproduce the above copyright
     13       1.1    leo  *    notice, this list of conditions and the following disclaimer in the
     14       1.1    leo  *    documentation and/or other materials provided with the distribution.
     15       1.1    leo  * 3. All advertising materials mentioning features or use of this software
     16       1.1    leo  *    must display the following acknowledgement:
     17       1.1    leo  *        This product includes software developed by Waldi Ravens.
     18       1.1    leo  * 4. The name of the author may not be used to endorse or promote products
     19       1.1    leo  *    derived from this software without specific prior written permission.
     20       1.1    leo  *
     21       1.1    leo  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     22       1.1    leo  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     23       1.1    leo  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     24       1.1    leo  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     25       1.1    leo  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     26       1.1    leo  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     27       1.1    leo  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     28       1.1    leo  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     29       1.1    leo  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     30       1.1    leo  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     31       1.1    leo  */
     32       1.1    leo 
     33       1.1    leo #include <sys/types.h>
     34       1.1    leo #include <stdlib.h>
     35       1.1    leo #include <stdio.h>
     36       1.1    leo #include "libtos.h"
     37       1.1    leo #include "aptck.h"
     38       1.1    leo #include "ahdilbl.h"
     39       1.1    leo #include "disklbl.h"
     40       1.1    leo 
     41       1.1    leo static int	dkcksum    PROTO((struct disklabel *));
     42       1.1    leo static int	bsd_label  PROTO((disk_t *, u_int));
     43       1.1    leo static int	ahdi_label PROTO((disk_t *));
     44       1.1    leo static int	ahdi_display PROTO((disk_t *));
     45       1.1    leo static u_int	ahdi_getparts PROTO((disk_t *, u_int, u_int));
     46       1.1    leo 
     47       1.1    leo int
     48       1.1    leo readdisklabel(dd)
     49       1.1    leo 	disk_t	*dd;
     50       1.1    leo {
     51       1.1    leo 	int	e;
     52       1.1    leo 
     53       1.3    leo 	printf("Device     : %s (%s) [%s]\n", dd->sname, dd->fname,
     54       1.3    leo 							 dd->product);
     55       1.1    leo 	printf("Medium size: %lu sectors\n", (u_long)dd->msize);
     56       1.1    leo 	printf("Sector size: %lu bytes\n\n", (u_long)dd->bsize);
     57       1.1    leo 
     58       1.1    leo 	e = bsd_label(dd, LABELSECTOR);
     59       1.1    leo 	if (e < 0) {
     60       1.1    leo 		printf("Device I/O error (hardware problem?)\n\n");
     61       1.1    leo 		return(-1);
     62       1.1    leo 	}
     63       1.1    leo 	if (!e) {
     64       1.1    leo 		printf("NetBSD/Atari format, boot block: "
     65       1.1    leo 		       "sector %u labeloffset %u\n\n",
     66       1.1    leo 		       dd->bblock, dd->lblofs);
     67       1.1    leo 		return(0);
     68       1.1    leo 	}
     69       1.1    leo 
     70       1.1    leo 	e = ahdi_label(dd);
     71       1.1    leo 	if (e < 0) {
     72       1.1    leo 		printf("Device I/O error (hardware problem?)\n\n");
     73       1.1    leo 		return(-1);
     74       1.1    leo 	}
     75       1.1    leo 	if (!e) {
     76       1.1    leo 		printf("AHDI format, NetBSD boot block: ");
     77       1.1    leo 		if (dd->bblock != NO_BOOT_BLOCK)
     78       1.1    leo 			printf("sector %u labeloffset %u\n\n",
     79       1.1    leo 			       dd->bblock, dd->lblofs);
     80       1.1    leo 		else printf("none\n\n");
     81       1.1    leo 		return(0);
     82       1.1    leo 	}
     83       1.1    leo 
     84       1.1    leo 	printf("Unknown label format.\n\n");
     85       1.1    leo 	return(-1);
     86       1.1    leo }
     87       1.1    leo 
     88       1.1    leo static int
     89       1.1    leo bsd_label(dd, offset)
     90       1.1    leo 	disk_t		*dd;
     91       1.1    leo 	u_int		offset;
     92       1.1    leo {
     93       1.1    leo 	u_char		*bblk;
     94       1.1    leo 	u_int		nsec;
     95       1.1    leo 	int		rv;
     96       1.1    leo 
     97       1.2    leo 	nsec = (BBMINSIZE + (dd->bsize - 1)) / dd->bsize;
     98       1.1    leo 	bblk = disk_read(dd, offset, nsec);
     99       1.1    leo 	if (bblk) {
    100       1.3    leo 		u_int	*end, *p;
    101       1.1    leo 
    102       1.3    leo 		end = (u_int *)&bblk[BBMINSIZE - sizeof(struct disklabel)];
    103       1.3    leo 		rv  = 1;
    104       1.3    leo 		for (p = (u_int *)bblk; p < end; ++p) {
    105       1.3    leo 			struct disklabel *dl = (struct disklabel *)&p[1];
    106       1.3    leo 			if (  (  (p[0] == NBDAMAGIC && offset == 0)
    107       1.3    leo 			      || (p[0] == AHDIMAGIC && offset != 0)
    108       1.3    leo 			      || (u_char *)dl - bblk == 7168
    109       1.3    leo 			      )
    110       1.3    leo 			   && dl->d_npartitions <= MAXPARTITIONS
    111       1.3    leo 			   && dl->d_magic2 == DISKMAGIC
    112       1.3    leo 			   && dl->d_magic  == DISKMAGIC
    113       1.3    leo 			   && dkcksum(dl)  == 0
    114       1.3    leo 			   )	{
    115       1.3    leo 		    		dd->lblofs = (u_char *)dl - bblk;
    116       1.1    leo 		    		dd->bblock = offset;
    117       1.1    leo 				rv = 0;
    118       1.1    leo 				break;
    119       1.1    leo 			}
    120       1.1    leo 		}
    121       1.1    leo 		free(bblk);
    122       1.1    leo 	}
    123       1.1    leo 	else rv = -1;
    124       1.1    leo 
    125       1.1    leo 	return(rv);
    126       1.1    leo }
    127       1.1    leo 
    128       1.1    leo static int
    129       1.1    leo dkcksum(dl)
    130       1.1    leo 	struct disklabel *dl;
    131       1.1    leo {
    132       1.1    leo 	u_short	*start, *end, sum = 0;
    133       1.1    leo 
    134       1.1    leo 	start = (u_short *)dl;
    135       1.1    leo 	end   = (u_short *)&dl->d_partitions[dl->d_npartitions];
    136       1.1    leo 	while (start < end)
    137       1.1    leo 		sum ^= *start++;
    138       1.1    leo 	return(sum);
    139       1.1    leo }
    140       1.1    leo 
    141       1.1    leo int
    142       1.1    leo ahdi_label(dd)
    143       1.1    leo 	disk_t	*dd;
    144       1.1    leo {
    145       1.1    leo 	u_int	i;
    146       1.1    leo 	int	e;
    147       1.1    leo 
    148       1.1    leo 	/*
    149       1.1    leo 	 * The AHDI format requires a specific block size.
    150       1.1    leo 	 */
    151       1.1    leo 	if (dd->bsize != AHDI_BSIZE)
    152       1.1    leo 		return(1);
    153       1.1    leo 
    154       1.1    leo 	/*
    155       1.1    leo 	 * Fetch the AHDI partition descriptors.
    156       1.1    leo 	 */
    157       1.1    leo 	i = ahdi_getparts(dd, AHDI_BBLOCK, AHDI_BBLOCK);
    158       1.1    leo 	if (i) {
    159       1.1    leo 		if (i < dd->msize)
    160       1.1    leo 			return(-1);	/* disk read error		*/
    161       1.1    leo 		else return(1);		/* reading past end of medium	*/
    162       1.1    leo 	}
    163       1.1    leo 
    164       1.1    leo 	/*
    165       1.1    leo 	 * Display and perform sanity checks.
    166       1.1    leo 	 */
    167       1.1    leo 	i = ahdi_display(dd);
    168       1.1    leo 	if (i)
    169       1.1    leo 		return(i);
    170       1.1    leo 
    171       1.1    leo 	/*
    172       1.1    leo 	 * Search for a NetBSD disk label
    173       1.1    leo 	 */
    174       1.1    leo 	dd->bblock = NO_BOOT_BLOCK;
    175       1.1    leo 	for (i = 0; i < dd->nparts; ++i) {
    176       1.1    leo 		part_t	*pd = &dd->parts[i];
    177       1.1    leo 		u_int	id  = *((u_int32_t *)&pd->id) >> 8;
    178       1.1    leo 		if (id == AHDI_PID_NBD || id == AHDI_PID_RAW) {
    179       1.1    leo 			u_int	offs = pd->start;
    180       1.1    leo 			if ((e = bsd_label(dd, offs)) < 0) {
    181       1.1    leo 				return(e);		/* I/O error */
    182       1.1    leo 			}
    183       1.1    leo 			if (!e) {
    184       1.1    leo 				dd->bblock = offs;	/* got it */
    185       1.1    leo 				return(0);
    186       1.1    leo 			}
    187       1.1    leo 			if (id == AHDI_PID_NBD && dd->bblock == NO_BOOT_BLOCK)
    188       1.1    leo 				dd->bblock = offs;
    189       1.1    leo 		}
    190       1.1    leo 	}
    191       1.1    leo 	return(0);
    192       1.1    leo }
    193       1.1    leo 
    194       1.1    leo static int
    195       1.1    leo root_cmp(x1, x2)
    196       1.1    leo 	const void	*x1, *x2;
    197       1.1    leo {
    198       1.1    leo 	const u_int	*r1 = x1,
    199       1.1    leo 			*r2 = x2;
    200       1.1    leo 
    201       1.1    leo 	if (*r1 < *r2)
    202       1.1    leo 		return(-1);
    203       1.1    leo 	if (*r1 > *r2)
    204       1.1    leo 		return(1);
    205       1.1    leo 	return(0);
    206       1.1    leo }
    207       1.1    leo 
    208       1.1    leo static int
    209       1.1    leo part_cmp(x1, x2)
    210       1.1    leo 	const void	*x1, *x2;
    211       1.1    leo {
    212       1.1    leo 	const part_t	*p1 = x1,
    213       1.1    leo 			*p2 = x2;
    214       1.1    leo 
    215       1.1    leo 	if (p1->start < p2->start)
    216       1.1    leo 		return(-1);
    217       1.1    leo 	if (p1->start > p2->start)
    218       1.1    leo 		return(1);
    219       1.1    leo 	if (p1->end < p2->end)
    220       1.1    leo 		return(-1);
    221       1.1    leo 	if (p1->end > p2->end)
    222       1.1    leo 		return(1);
    223       1.1    leo 	if (p1->rsec < p2->rsec)
    224       1.1    leo 		return(-1);
    225       1.1    leo 	if (p1->rsec > p2->rsec)
    226       1.1    leo 		return(1);
    227       1.1    leo 	if (p1->rent < p2->rent)
    228       1.1    leo 		return(-1);
    229       1.1    leo 	if (p1->rent > p2->rent)
    230       1.1    leo 		return(1);
    231       1.1    leo 	return(0);
    232       1.1    leo }
    233       1.1    leo 
    234       1.1    leo static int
    235       1.1    leo ahdi_display(dd)
    236       1.1    leo 	disk_t	*dd;
    237       1.1    leo {
    238       1.1    leo 	int	i, j, rv = 0;
    239       1.1    leo 
    240       1.1    leo 	printf("Start of bad sector list : %u\n", dd->bslst);
    241       1.1    leo 	if (dd->bslst == 0) {
    242       1.1    leo 		printf("* Illegal value (zero) *\n"); rv = 1;
    243       1.1    leo 	}
    244       1.1    leo 	printf("End of bad sector list   : %u\n", dd->bslend);
    245       1.1    leo 	if (dd->bslend == 0) {
    246       1.1    leo 		printf("* Illegal value (zero) *\n"); rv = 1;
    247       1.1    leo 	}
    248       1.1    leo 	printf("Medium size (in root sec): %u\n", dd->hdsize);
    249       1.1    leo 	if (dd->hdsize == 0) {
    250       1.1    leo 		printf("* Illegal value (zero) *\n"); rv = 1;
    251       1.1    leo 	}
    252       1.1    leo 
    253       1.1    leo 	qsort(dd->roots, dd->nroots, sizeof *dd->roots, root_cmp);
    254       1.1    leo 	qsort(dd->parts, dd->nparts, sizeof *dd->parts, part_cmp);
    255       1.1    leo 	printf("\n    root  desc   id     start       end    MBs\n");
    256       1.1    leo 
    257       1.1    leo 	for (i = 0; i < dd->nparts; ++i) {
    258       1.1    leo 		part_t	*p1 = &dd->parts[i];
    259       1.1    leo 		u_int	megs = p1->end - p1->start + 1,
    260       1.1    leo 			blpm = (1024 * 1024) / dd->bsize;
    261       1.1    leo 		megs = (megs + (blpm >> 1)) / blpm;
    262       1.1    leo 		printf("%8u  %4u  %s  %8u  %8u  (%3u)\n",
    263       1.1    leo 			p1->rsec, p1->rent, p1->id,
    264       1.1    leo 			p1->start, p1->end, megs);
    265       1.1    leo 		for (j = 0; j < dd->nroots; ++j) {
    266       1.1    leo 			u_int	aux = dd->roots[j];
    267       1.1    leo 			if (aux >= p1->start && aux <= p1->end) {
    268  1.3.44.1  lukem 				printf("FATAL: auxiliary root at %u\n", aux);
    269       1.3    leo 				rv = 1;
    270       1.1    leo 			}
    271       1.1    leo 		}
    272       1.1    leo 		for (j = i; j--;) {
    273       1.3    leo 		    part_t	*p2 = &dd->parts[j];
    274       1.3    leo 		    if (p1->start >= p2->start && p1->start <= p2->end) {
    275       1.3    leo 			printf("FATAL: clash with %u/%u\n", p2->rsec, p2->rent);
    276       1.3    leo 			rv = 1;
    277       1.3    leo 		    }
    278       1.3    leo 		    if (p2->start >= p1->start && p2->start <= p1->end) {
    279       1.3    leo 			printf("FATAL: clash with %u/%u\n", p2->rsec, p2->rent);
    280       1.3    leo 			rv = 1;
    281       1.3    leo 		    }
    282       1.1    leo 		}
    283       1.1    leo 		if (p1->start >= dd->bslst && p1->start <= dd->bslend) {
    284       1.3    leo 		    printf("FATAL: partition overlaps with bad sector list\n");
    285       1.3    leo 		    rv = 1;
    286       1.1    leo 		}
    287       1.1    leo 		if (dd->bslst >= p1->start && dd->bslst <= p1->end) {
    288       1.3    leo 		    printf("FATAL: partition overlaps with bad sector list\n");
    289       1.3    leo 		    rv = 1;
    290       1.1    leo 		}
    291       1.1    leo 	}
    292       1.1    leo 
    293  1.3.44.1  lukem 	printf("\nTotal number of auxiliary roots: %u\n", dd->nroots);
    294       1.1    leo 	printf("Total number of partitions    : %u\n", dd->nparts);
    295       1.1    leo 	if (dd->nparts == 0) {
    296       1.1    leo 		printf("* Weird # of partitions (zero) *\n"); rv = 1;
    297       1.1    leo 	}
    298       1.1    leo 	if (dd->nparts > AHDI_MAXPARTS) {
    299       1.1    leo 		printf("* Too many AHDI partitions for the default NetBSD "
    300       1.1    leo 			"kernel *\n  Increase MAXAUXROOTS in src/sys/arch/"
    301       1.1    leo 			"atari/include/disklabel.h\n  to at least %u, and "
    302       1.1    leo 			"recompile the NetBSD kernel.\n", dd->nroots);
    303       1.1    leo 		rv = -1;
    304       1.1    leo 	}
    305       1.1    leo 	return(rv);
    306       1.1    leo }
    307       1.1    leo 
    308       1.1    leo static u_int
    309       1.1    leo ahdi_getparts(dd, rsec, esec)
    310       1.1    leo 	disk_t			*dd;
    311       1.1    leo 	u_int			rsec,
    312       1.1    leo 				esec;
    313       1.1    leo {
    314       1.1    leo 	struct ahdi_part	*part, *end;
    315       1.1    leo 	struct ahdi_root	*root;
    316       1.1    leo 	u_int			rv;
    317       1.1    leo 
    318       1.1    leo 	root = disk_read(dd, rsec, 1);
    319       1.1    leo 	if (!root) {
    320       1.1    leo 		rv = rsec + (rsec == 0);
    321       1.1    leo 		goto done;
    322       1.1    leo 	}
    323       1.1    leo 
    324       1.1    leo 	if (rsec == AHDI_BBLOCK)
    325       1.1    leo 		end = &root->ar_parts[AHDI_MAXRPD];
    326       1.1    leo 	else end = &root->ar_parts[AHDI_MAXARPD];
    327       1.1    leo 	for (part = root->ar_parts; part < end; ++part) {
    328       1.1    leo 		u_int	id = *((u_int32_t *)&part->ap_flg);
    329       1.1    leo 		if (!(id & 0x01000000))
    330       1.1    leo 			continue;
    331       1.1    leo 		if ((id &= 0x00ffffff) == AHDI_PID_XGM) {
    332       1.1    leo 			u_int	offs = part->ap_offs + esec;
    333       1.1    leo 			u_int	i = ++dd->nroots;
    334       1.1    leo 			dd->roots = xrealloc(dd->roots, i * sizeof *dd->roots);
    335       1.1    leo 			dd->roots[--i] = offs;
    336       1.3    leo 			rv = ahdi_getparts(dd, offs,
    337       1.3    leo 					esec == AHDI_BBLOCK ? offs : esec);
    338       1.1    leo 			if (rv)
    339       1.1    leo 				goto done;
    340       1.1    leo 		} else {
    341       1.1    leo 			part_t	*p;
    342       1.1    leo 			u_int	i = ++dd->nparts;
    343       1.1    leo 			dd->parts = xrealloc(dd->parts, i * sizeof *dd->parts);
    344       1.1    leo 			p = &dd->parts[--i];
    345       1.1    leo 			*((u_int32_t *)&p->id) = id << 8;
    346       1.1    leo 			p->start = part->ap_offs + rsec;
    347       1.1    leo 			p->end   = p->start + part->ap_size - 1;
    348       1.1    leo 			p->rsec  = rsec;
    349       1.1    leo 			p->rent  = part - root->ar_parts;
    350       1.1    leo 		}
    351       1.1    leo 	}
    352       1.1    leo 	dd->hdsize = root->ar_hdsize;
    353       1.1    leo 	dd->bslst  = root->ar_bslst;
    354       1.1    leo 	dd->bslend = root->ar_bslst + root->ar_bslsize - 1;
    355       1.1    leo 	rv = 0;
    356       1.1    leo done:
    357       1.1    leo 	free(root);
    358       1.1    leo 	return(rv);
    359       1.1    leo }
    360