Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 8 Feb 2003 23:33:34 -0600
From:      Juli Mallett <jmallett@FreeBSD.org>
To:        freebsd-mips@FreeBSD.org
Subject:   GEOM fx module.
Message-ID:  <20030208233334.A24836@FreeBSD.org>

next in thread | raw e-mail | index | archive | help
I've added a geom module for fx-labelled disks to Perforce, and I think it's
right given SGI's documentation, and NetBSD, if anyone wants to play with it,
and doesn't want to bother grabbing it from Perforce or the WWW interface
to such, here it is.  Let me know if you think I missed something, it's my
first try at writing such.  It recognises a dd of an SGI cdrom, and I think
it gets the partition info right, but hey, let me know :)

%%%
/*-
 * Copyright (c) 2003 Juli Mallett
 * Copyright (c) 2002 Poul-Henning Kamp
 * Copyright (c) 2002 Networks Associates Technology, Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. The names of the authors may not be used to endorse or promote
 *    products derived from this software without specific prior written
 *    permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 * $FreeBSD$
 */


#include <sys/param.h>
#ifndef _KERNEL
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <signal.h>
#include <err.h>
#else
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/conf.h>
#include <sys/bio.h>
#include <sys/malloc.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#endif
#include <geom/geom.h>
#include <geom/geom_slice.h>
#include <machine/endian.h>

#define FX_CLASS_NAME	"FX"
#define	FX_LABEL_MAGIC	0xbe5a941
#define	FX_NPARTS	16

static const char *fx_typename[] = {
	"Volume Header",
	"Repl Trks",
	"Repl Secs",
	"Raw",
	"4.2BSD",
	"SysV",
	"Volume",
	"EFS",
	"LVol",
	"RLVol",
	"XFS",
	"XFSLog",
	"XLV",
	"XVM"
};

struct dparms {
	u_int8_t	dp_skew;
	u_int8_t	dp_gap1;
	u_int8_t	dp_gap2;
	u_int8_t	dp_spares_cyl;
	u_int16_t	dp_cyls;
	u_int16_t	dp_shd0;
	u_int16_t	dp_trks0;
	u_int8_t	dp_ctq_depth;
	u_int8_t	dp_cylshi;
	u_int16_t	dp_unused;
	u_int16_t	dp_secs;
	u_int16_t	dp_secbytes;
	u_int16_t	dp_interleave;
	u_int32_t	dp_flags;
	u_int32_t	dp_datarate;
	u_int32_t	dp_nretries;
	u_int32_t	dp_mspw;
	u_int16_t	dp_xgap1;
	u_int16_t	dp_xsync;
	u_int16_t	dp_xrdly;
	u_int16_t	dp_xgap2;
	u_int16_t	dp_xrgate;
	u_int16_t	dp_xwcont;
} __packed;

struct voldir {
	char		vd_name[8];
	int32_t		vd_addr;
	int32_t		vd_size;
} __packed;

struct volpart {
	int32_t		vp_size;
	int32_t		vp_begin;
	int32_t		vp_type;
} __packed;

struct volhdr {
	u_int32_t	vh_magic;
	int16_t		vh_root;
	int16_t		vh_swap;
	char		vh_kernel[16];
	struct dparms	vh_dp;
	struct voldir	vh_dir[15];
	struct volpart	vh_part[FX_NPARTS];
	int32_t		vh_csum;
	int32_t		vh_unused;
} __packed;

struct g_fx_softc {
	struct volhdr	sc_volhdr;
};

static void
g_fx_swap_volpart(struct volpart *vp)
{
	vp->vp_size = g_dec_be4((u_char *)&vp->vp_size);
	vp->vp_begin = g_dec_be4((u_char *)&vp->vp_size);
	vp->vp_type = g_dec_be4((u_char *)&vp->vp_type);
}

static const char *
g_fx_type(int32_t type)
{
	static size_t ntypes = sizeof fx_typename / sizeof fx_typename[0];

	if (type < 0 || type >= ntypes) {
		return ("Erroneous partition type.");
	}
	return (fx_typename[type]);
}

static int
g_fx_cksum(struct volhdr *vh)
{
	int32_t *words;
	int32_t sum;
	int i;

	sum = 0;
	words = (int32_t *)vh;

	for (i = 0; i < 512 / sizeof *words; i++)
		sum += g_dec_be4((u_char *)&words[i]);
	return sum;
}

static int
g_fx_start(struct bio *bp)
{
	struct g_geom *gp;
	struct g_fx_softc *ms;
	struct g_slicer *gsp;

	gp = bp->bio_to->geom;
	gsp = gp->softc;
	ms = gsp->softc;
	return (0);
}

static void
g_fx_dumpconf(struct sbuf *sb, const char *indent, struct g_geom *gp, struct g_consumer *cp __unused, struct g_provider *pp)
{
	struct g_slicer *gsp;
	struct g_fx_softc *ms;

	gsp = gp->softc;
	ms = gsp->softc;
	g_slice_dumpconf(sb, indent, gp, cp, pp);
	if (indent == NULL) {
#if 0
		sbuf_printf(sb, " sc %u hd %u",
		    ms->sc_label.dp.dp_secs, 0);
#endif
	}
}

static struct g_geom *
g_fx_taste(struct g_class *mp, struct g_provider *pp, int flags)
{
	struct g_geom *gp;
	struct g_consumer *cp;
	int error, i, npart;
	u_char *buf;
	struct g_fx_softc *ms;
	off_t mediasize;
	u_int sectorsize;
	struct g_slicer *gsp;
	struct volhdr *label;
	struct volpart *vp;

	g_trace(G_T_TOPOLOGY, "g_fx_taste(%s,%s)", mp->name, pp->name);
	g_topology_assert();
	if (flags == G_TF_NORMAL &&
	    !strcmp(pp->geom->class->name, FX_CLASS_NAME))
		return (NULL);
	gp = g_slice_new(mp, FX_NPARTS, pp, &cp, &ms, sizeof *ms, g_fx_start);
	if (gp == NULL)
		return (NULL);
	gsp = gp->softc;
	g_topology_unlock();
	gp->dumpconf = g_fx_dumpconf;
	npart = 0;
	while (1) {	/* a trick to allow us to use break */
		if (gp->rank != 2 && flags == G_TF_NORMAL)
			break;
		sectorsize = cp->provider->sectorsize;
		if (sectorsize < 512)
			break;
		gsp->frontstuff = 16 * sectorsize;	/* XXX */
		mediasize = cp->provider->mediasize;
		buf = g_read_data(cp, 0, sizeof (struct volhdr), &error);
		if (buf == NULL || error != 0)
			break;
		label = (struct volhdr *)buf;
		if (g_dec_be4((u_char *)&label->vh_magic) != FX_LABEL_MAGIC)
			break;
		error = g_fx_cksum(label);
		if (error != 0) {
			if (bootverbose) {
				printf("Found a bad label on %s (sum %d)\n",
				       pp->name, error);
			}
			break;
		}
		ms->sc_volhdr = *label;
		for (i = 0; i < FX_NPARTS; i++) {
			vp = &label->vh_part[i];
			g_fx_swap_volpart(vp);
			if (!vp->vp_size)
				continue;
			g_topology_lock();
			g_slice_config(gp, i, G_SLICE_CONFIG_SET,
			    vp->vp_begin, vp->vp_size, sectorsize,
			    "%s%c", pp->name, 'a' + i);
			g_topology_unlock();
			if (bootverbose) {
				printf("Added %s%c of type %d (%s)\n",
				       pp->name, 'a' + i, vp->vp_type,
				       g_fx_type(vp->vp_type));
			}
			npart++;
		}
		if (bootverbose) {
			printf("Configured %d partitions on %s\n",
			       npart, pp->name);
		}
		break;
	}
	g_topology_lock();
	g_access_rel(cp, -1, 0, 0);
	if (LIST_EMPTY(&gp->provider)) {
		g_std_spoiled(cp);
		return (NULL);
	}
	return (gp);
}

static struct g_class g_fx_class = {
	FX_CLASS_NAME,
	g_fx_taste,
	NULL,
	G_CLASS_INITIALIZER
};

DECLARE_GEOM_CLASS(g_fx_class, g_fx);
%%%

Thanx,
juli.
-- 
Juli Mallett <jmallett@FreeBSD.org>
AIM: BSDFlata -- IRC: juli on EFnet
OpenDarwin, Mono, FreeBSD Developer
ircd-hybrid Developer, EFnet addict
FreeBSD on MIPS-Anything on FreeBSD

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-mips" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20030208233334.A24836>