geom_sunlabel.c revision 113011
179754Sdd/*-
221026Sjoerg * Copyright (c) 2002 Poul-Henning Kamp
379754Sdd * Copyright (c) 2002 Networks Associates Technology, Inc.
421026Sjoerg * All rights reserved.
579754Sdd *
621026Sjoerg * This software was developed for the FreeBSD Project by Poul-Henning Kamp
721026Sjoerg * and NAI Labs, the Security Research Division of Network Associates, Inc.
821026Sjoerg * under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the
921026Sjoerg * DARPA CHATS research program.
1021026Sjoerg *
1121026Sjoerg * Redistribution and use in source and binary forms, with or without
1221026Sjoerg * modification, are permitted provided that the following conditions
1321026Sjoerg * are met:
1421026Sjoerg * 1. Redistributions of source code must retain the above copyright
1521026Sjoerg *    notice, this list of conditions and the following disclaimer.
1621026Sjoerg * 2. Redistributions in binary form must reproduce the above copyright
1721026Sjoerg *    notice, this list of conditions and the following disclaimer in the
1821026Sjoerg *    documentation and/or other materials provided with the distribution.
1921026Sjoerg * 3. The names of the authors may not be used to endorse or promote
2021026Sjoerg *    products derived from this software without specific prior written
2121026Sjoerg *    permission.
2221026Sjoerg *
2321026Sjoerg * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
2421026Sjoerg * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2579754Sdd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2650476Speter * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2721026Sjoerg * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28337254Sasomers * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29206622Suqs * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3021026Sjoerg * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3121026Sjoerg * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3279754Sdd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3321111Smpp * SUCH DAMAGE.
3421026Sjoerg *
3559516Sphantom * $FreeBSD: head/sys/geom/geom_sunlabel.c 113011 2003-04-03 11:36:53Z phk $
3659516Sphantom */
3721026Sjoerg
3884306Sru
3984306Sru#include <sys/param.h>
4084306Sru#include <sys/endian.h>
4184306Sru#ifndef _KERNEL
4221026Sjoerg#include <stdio.h>
4321026Sjoerg#include <string.h>
4421026Sjoerg#include <stdlib.h>
4521026Sjoerg#include <signal.h>
4621026Sjoerg#include <sys/errno.h>
4721026Sjoerg#include <err.h>
4821111Smpp#else
4921026Sjoerg#include <sys/systm.h>
5021026Sjoerg#include <sys/kernel.h>
51175336Sjhb#include <sys/conf.h>
5221026Sjoerg#include <sys/bio.h>
5321026Sjoerg#include <sys/malloc.h>
5421026Sjoerg#include <sys/lock.h>
5521026Sjoerg#include <sys/mutex.h>
56175336Sjhb#endif
57175336Sjhb#include <geom/geom.h>
5821026Sjoerg#include <geom/geom_slice.h>
5921026Sjoerg#include <machine/endian.h>
6021026Sjoerg
6121452Smpp#define SUNLABEL_CLASS_NAME "SUN"
6221026Sjoerg
6321026Sjoergstruct g_sunlabel_softc {
6421111Smpp	int sectorsize;
65131504Sru	int nheads;
66131504Sru	int nsects;
6721153Salex	int nalt;
6821026Sjoerg};
6921026Sjoerg
7021452Smppstatic int
7121026Sjoergg_sunlabel_modify(struct g_geom *gp, struct g_sunlabel_softc *ms, u_char *sec0)
7221452Smpp{
7321026Sjoerg	int i, error;
7421026Sjoerg	u_int u, v, csize;
7521111Smpp
7621026Sjoerg	/* The second last short is a magic number */
7721153Salex	if (be16dec(sec0 + 508) != 0xdabe)
7821026Sjoerg		return (EBUSY);
7921111Smpp
8021026Sjoerg	/* The shortword parity of the entire thing must be even */
8121452Smpp	u = 0;
8221026Sjoerg	for (i = 0; i < 512; i += 2)
8321452Smpp		u ^= be16dec(sec0 + i);
8421026Sjoerg	if (u != 0)
8521026Sjoerg		return(EBUSY);
86112541Scharnier
87112541Scharnier	csize = be16dec(sec0 + 436) * be16dec(sec0 + 438);
88112541Scharnier
8921111Smpp	for (i = 0; i < 8; i++) {
90131504Sru		v = be32dec(sec0 + 444 + i * 8);
91131504Sru		u = be32dec(sec0 + 448 + i * 8);
92131504Sru		g_topology_lock();
93131504Sru		error = g_slice_config(gp, i, G_SLICE_CONFIG_CHECK,
9421026Sjoerg		    ((off_t)v * csize) << 9ULL,
9521026Sjoerg		    ((off_t)u) << 9ULL,
96131504Sru		    ms->sectorsize,
97131504Sru		    "%s%c", gp->name, 'a' + i);
98131504Sru		g_topology_unlock();
99131504Sru		if (error)
10021452Smpp			return (error);
10121452Smpp	}
10221452Smpp	for (i = 0; i < 8; i++) {
10321026Sjoerg		v = be32dec(sec0 + 444 + i * 8);
10421452Smpp		u = be32dec(sec0 + 448 + i * 8);
10521026Sjoerg		g_topology_lock();
10621111Smpp		g_slice_config(gp, i, G_SLICE_CONFIG_SET,
10721026Sjoerg		    ((off_t)v * csize) << 9ULL,
108112541Scharnier		    ((off_t)u) << 9ULL,
109112541Scharnier		    ms->sectorsize,
110112541Scharnier		    "%s%c", gp->name, 'a' + i);
11121026Sjoerg		g_topology_unlock();
112112541Scharnier	}
113112541Scharnier	ms->nalt = be16dec(sec0 + 434);
114112541Scharnier	ms->nheads = be16dec(sec0 + 436);
115112541Scharnier	ms->nsects = be16dec(sec0 + 438);
11621026Sjoerg
117175336Sjhb	return (0);
11821111Smpp}
119175336Sjhb
12021026Sjoergstatic int
121175336Sjhbg_sunlabel_start(struct bio *bp)
122175336Sjhb{
123290735Ssmh	struct g_geom *gp;
124175336Sjhb	struct g_sunlabel_softc *ms;
125175336Sjhb	struct g_slicer *gsp;
126175336Sjhb
127175336Sjhb	gp = bp->bio_to->geom;
128175336Sjhb	gsp = gp->softc;
129175336Sjhb	ms = gsp->softc;
13021026Sjoerg	return (0);
13121026Sjoerg}
13221111Smpp
13321026Sjoergstatic void
13421026Sjoergg_sunlabel_dumpconf(struct sbuf *sb, const char *indent, struct g_geom *gp, struct g_consumer *cp __unused, struct g_provider *pp)
13521026Sjoerg{
13621026Sjoerg	struct g_slicer *gsp;
13721026Sjoerg	struct g_sunlabel_softc *ms;
13821026Sjoerg
13921026Sjoerg	gsp = gp->softc;
14021026Sjoerg	ms = gsp->softc;
14121026Sjoerg	g_slice_dumpconf(sb, indent, gp, cp, pp);
14221026Sjoerg	if (indent == NULL) {
14321026Sjoerg		sbuf_printf(sb, " sc %u hd %u alt %u",
14449751Schris		    ms->nsects, ms->nheads, ms->nalt);
14521026Sjoerg	}
146337254Sasomers}
147337254Sasomers
148337254Sasomersstatic struct g_geom *
149337254Sasomersg_sunlabel_taste(struct g_class *mp, struct g_provider *pp, int flags)
150337254Sasomers{
151337254Sasomers	struct g_geom *gp;
152337254Sasomers	struct g_consumer *cp;
153337254Sasomers	int error, i, npart;
154337254Sasomers	u_char *buf;
155337254Sasomers	struct g_sunlabel_softc *ms;
156337254Sasomers	off_t mediasize;
157337254Sasomers	struct g_slicer *gsp;
158337254Sasomers
159337254Sasomers	g_trace(G_T_TOPOLOGY, "g_sunlabel_taste(%s,%s)", mp->name, pp->name);
160337254Sasomers	g_topology_assert();
161	if (flags == G_TF_NORMAL &&
162	    !strcmp(pp->geom->class->name, SUNLABEL_CLASS_NAME))
163		return (NULL);
164	gp = g_slice_new(mp, 8, pp, &cp, &ms, sizeof *ms, g_sunlabel_start);
165	if (gp == NULL)
166		return (NULL);
167	gsp = gp->softc;
168	g_topology_unlock();
169	gp->dumpconf = g_sunlabel_dumpconf;
170	npart = 0;
171	do {	/* a trick to allow us to use break */
172		if (gp->rank != 2 && flags == G_TF_NORMAL)
173			break;
174		ms->sectorsize = cp->provider->sectorsize;
175		if (ms->sectorsize < 512)
176			break;
177		gsp->frontstuff = 16 * ms->sectorsize;
178		mediasize = cp->provider->mediasize;
179		buf = g_read_data(cp, 0, ms->sectorsize, &error);
180		if (buf == NULL || error != 0)
181			break;
182
183		if (bootverbose) {
184			g_hexdump(buf, 128);
185			for (i = 0; i < 8; i++) {
186				printf("part %d %u %u\n", i,
187				    be32dec(buf + 444 + i * 8),
188				    be32dec(buf + 448 + i * 8));
189			}
190			printf("v_version = %d\n", be32dec(buf + 128));
191			printf("v_nparts = %d\n", be16dec(buf + 140));
192			for (i = 0; i < 8; i++) {
193				printf("v_part[%d] = %d %d\n",
194				    i, be16dec(buf + 142 + i * 4),
195				    be16dec(buf + 144 + i * 4));
196			}
197			printf("v_sanity %x\n", be32dec(buf + 186));
198			printf("v_version = %d\n", be32dec(buf + 128));
199			printf("v_rpm %d\n", be16dec(buf + 420));
200			printf("v_totalcyl %d\n", be16dec(buf + 422));
201			printf("v_cyl %d\n", be16dec(buf + 432));
202			printf("v_alt %d\n", be16dec(buf + 434));
203			printf("v_head %d\n", be16dec(buf + 436));
204			printf("v_sec %d\n", be16dec(buf + 438));
205		}
206
207		g_sunlabel_modify(gp, ms, buf);
208
209		break;
210	} while (0);
211	g_topology_lock();
212	g_access_rel(cp, -1, 0, 0);
213	if (LIST_EMPTY(&gp->provider)) {
214		g_std_spoiled(cp);
215		return (NULL);
216#ifdef notyet
217	} else {
218		g_slice_conf_hot(gp, 0, 0, ms->sectorsize);
219#endif
220	}
221	return (gp);
222}
223
224static struct g_class g_sunlabel_class = {
225	.name = SUNLABEL_CLASS_NAME,
226	.taste = g_sunlabel_taste,
227	G_CLASS_INITIALIZER
228};
229
230DECLARE_GEOM_CLASS(g_sunlabel_class, g_sunlabel);
231