1139749Simp/*	$NetBSD: check.c,v 1.5 2008/04/28 20:23:15 martin Exp $	*/
239217Sgibbs
339217Sgibbs/*
439217Sgibbs * Copyright (c) 1999 The NetBSD Foundation, Inc.
539217Sgibbs * All rights reserved.
655945Sgibbs *
755945Sgibbs * This code is derived from software contributed to The NetBSD Foundation
855945Sgibbs * by Julian Coleman, Waldi Ravens and Leo Weppelman.
955945Sgibbs *
1055945Sgibbs * Redistribution and use in source and binary forms, with or without
1155945Sgibbs * modification, are permitted provided that the following conditions
1255945Sgibbs * are met:
1355945Sgibbs * 1. Redistributions of source code must retain the above copyright
1455945Sgibbs *    notice, this list of conditions and the following disclaimer.
1555945Sgibbs * 2. Redistributions in binary form must reproduce the above copyright
1657679Sgibbs *    notice, this list of conditions and the following disclaimer in the
1739217Sgibbs *    documentation and/or other materials provided with the distribution.
1839217Sgibbs *
1957679Sgibbs * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
2057679Sgibbs * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
2157679Sgibbs * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2257679Sgibbs * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
2357679Sgibbs * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2457679Sgibbs * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2539217Sgibbs * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2639217Sgibbs * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2739217Sgibbs * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2857679Sgibbs * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2957679Sgibbs * POSSIBILITY OF SUCH DAMAGE.
3055945Sgibbs */
3139217Sgibbs
3239217Sgibbs#include "privahdi.h"
3339217Sgibbs
3439217Sgibbs/* Partitions which have errors */
3539217Sgibbsint	ahdi_errp1;
3639217Sgibbsint	ahdi_errp2;
3739217Sgibbs
3839217Sgibbs/*
3939217Sgibbs * Check partitions for consistency :
4039217Sgibbs *	GEM vs BGM
4139217Sgibbs *	Start sector > 2
4239217Sgibbs *	End sector < secperunit
4339217Sgibbs *	other partition overlap
4455945Sgibbs *	auxiliary root overlap
4539217Sgibbs *	Number of partitions in root/auxiliary root
4639217Sgibbs */
4739217Sgibbsint
4839217Sgibbsahdi_checklabel (struct ahdi_ptable *ptable)
4939217Sgibbs{
5039217Sgibbs	int		i, j, rcount, acount;
5139217Sgibbs	u_int32_t	i_end, j_end;
5239217Sgibbs
5339217Sgibbs	ahdi_errp1 = -1;
5439217Sgibbs	ahdi_errp2 = -1;
5539217Sgibbs
5639217Sgibbs	if (ptable->nparts < 1 || ptable->nparts > MAXPARTITIONS)
5739217Sgibbs		return (-2);
5839217Sgibbs
5939217Sgibbs	rcount = 0;
6039217Sgibbs	acount = 0;
61119418Sobrien
62119418Sobrien	for (i = 0; i < ptable->nparts; i++) {
63119418Sobrien
6439217Sgibbs		/* GEM vs BGM */
6539217Sgibbs		if (ptable->parts[i].size > 32768) {
6639217Sgibbs			if (AHDI_MKPID (ptable->parts[i].id[0],
67117126Sscottl			    ptable->parts[i].id[1], ptable->parts[i].id[2])
68129879Sphk			    == AHDI_PID_GEM) {
69117126Sscottl				ahdi_errp1 = i;
7039217Sgibbs				return (-3);
7139217Sgibbs			}
7259082Snyan		} else {
7359082Snyan			if (AHDI_MKPID (ptable->parts[i].id[0],
7459082Snyan			    ptable->parts[i].id[1], ptable->parts[i].id[2])
7539217Sgibbs			    == AHDI_PID_BGM) {
76119277Simp				ahdi_errp1 = i;
77119277Simp				return (-3);
7839217Sgibbs			}
7939217Sgibbs		}
8039217Sgibbs
81119690Sjhb		/* Need 2 free sectors at start for root and bad sector list */
82119690Sjhb		if (ptable->parts[i].start < 2) {
8339217Sgibbs			ahdi_errp1 = i;
8439217Sgibbs			return (-4);
8539217Sgibbs		}
8655945Sgibbs
8739217Sgibbs		i_end = ptable->parts[i].start + ptable->parts[i].size - 1;
8839217Sgibbs
8939217Sgibbs		/* Check partition does not extend past end of disk */
9039217Sgibbs		if (i_end >= ptable->secperunit) {
9139217Sgibbs			ahdi_errp1 = i;
9239217Sgibbs			return (-5);
9359082Snyan		}
9459082Snyan
9539217Sgibbs		for (j = i + 1; j < ptable->nparts; j++) {
9639217Sgibbs			/* Check for overlap with other partitions */
9739217Sgibbs			j_end = ptable->parts[j].start + ptable->parts[j].size
9839217Sgibbs			    - 1;
99155319Simp			if ((ptable->parts[j].start >= ptable->parts[i].start
10042012Sgibbs			    && ptable->parts[j].start <= i_end) ||
10142012Sgibbs			    (j_end >= ptable->parts[i].start &&
10242012Sgibbs			     j_end <= i_end)) {
10339217Sgibbs				ahdi_errp1 = i;
10459082Snyan				ahdi_errp2 = j;
10559082Snyan				return (-6);
10639217Sgibbs			}
10759082Snyan			/* Check number of partitions in auxiliary root */
10855945Sgibbs			if (ptable->parts[i].root &&
10959082Snyan			    ptable->parts[i].root == ptable->parts[j].root) {
11039217Sgibbs				ahdi_errp1 = i;
11159082Snyan				ahdi_errp2 = j;
112143164Simp				return (-9);
11339217Sgibbs			}
11459082Snyan		}
115143164Simp
11655945Sgibbs		for (j = i; j < ptable->nparts; j++)
11759082Snyan			/* Check for overlap with auxiliary root(s) */
11859082Snyan			if (ptable->parts[j].root >= ptable->parts[i].start &&
11959082Snyan			    ptable->parts[j].root <= i_end) {
120143164Simp				ahdi_errp1 = i;
12159082Snyan				return (-7);
12259082Snyan			}
12359082Snyan
124143164Simp		/* Count partitions in root/auxiliary roots */
12559082Snyan		if (ptable->parts[i].root)
12659082Snyan			acount++;
127143164Simp		else
12859082Snyan			rcount++;
12939217Sgibbs
13039217Sgibbs	}
13139217Sgibbs	/* Check number of partitions in root sector */
13239217Sgibbs	if (acount)
13359082Snyan		rcount++;
13439217Sgibbs	if (rcount > 4)
13539217Sgibbs		return (-8);
13659082Snyan	else
13759082Snyan		return (1);
13839217Sgibbs}
13939217Sgibbs