//freebsd/geom_nbsd/tags/0001-first-public/src/geom_nbsd.c |
---|
0,0 → 1,457 |
/*- |
* Copyright 2005, Anatoli Klassen <anatoli@aksoft.net> |
* All rights reserved. |
* |
* The code is based on code of geom_bsd module by Poul-Henning Kamp. |
* |
* Copyright (c) 2002 Poul-Henning Kamp |
* Copyright (c) 2002 Networks Associates Technology, Inc. |
* All rights reserved. |
* |
* This software was developed for the FreeBSD Project by Poul-Henning Kamp |
* and NAI Labs, the Security Research Division of Network Associates, Inc. |
* under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the |
* DARPA CHATS research program. |
* |
* 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. |
*/ |
/* |
* This is the method for dealing with BSD disklabels. It has been |
* extensively (by my standards at least) commented, in the vain hope that |
* it will serve as the source in future copy&paste operations. |
*/ |
#include <sys/param.h> |
#include <sys/systm.h> |
#include <sys/kernel.h> |
#include <sys/bio.h> |
#include <sys/malloc.h> |
#include <sys/lock.h> |
#include <sys/md5.h> |
#include <sys/errno.h> |
#include <geom/geom.h> |
#include <geom/geom_slice.h> |
#include "disklabel.h" |
#define NBSD_CLASS_NAME "NetBSD" |
#define LABELSIZE (148 + 16 * NBSD_MAXPARTITIONS) |
/* |
* Our private data about one instance. All the rest is handled by the |
* slice code and stored in its softc, so this is just the stuff |
* specific to BSD disklabels. |
*/ |
struct g_nbsd_softc { |
int mbrtype; |
off_t labeloffset; |
off_t mbroffset; |
off_t rawoffset; |
struct disklabel ondisk; |
u_char label[LABELSIZE]; |
u_char labelsum[16]; |
}; |
/* |
* Modify our slicer to match proposed disklabel, if possible. |
* This is where we make sure we don't do something stupid. |
*/ |
static int |
g_nbsd_modify(struct g_geom *gp, struct g_nbsd_softc *ms) |
{ |
char useable[NBSD_MAXPARTITIONS]; |
MD5_CTX md5sum; |
struct partition *ppp; |
struct g_slicer *gsp; |
struct g_consumer *cp; |
struct disklabel *dl; |
off_t rawoffset, fullsize, o; |
int i, error; |
u_int secsize, u; |
g_topology_assert(); |
gsp = gp->softc; |
dl = &ms->ondisk; |
/* Get dimensions of our device. */ |
cp = LIST_FIRST(&gp->consumer); |
secsize = cp->provider->sectorsize; |
/* ... or a smaller sector size. */ |
if (dl->d_secsize < secsize) { |
return (EINVAL); |
} |
/* ... or a non-multiple sector size. */ |
if (dl->d_secsize % secsize != 0) { |
return (EINVAL); |
} |
rawoffset = ms->mbroffset; |
fullsize = cp->provider->mediasize; |
for (i = 0; i < dl->d_npartitions; i++) { |
ppp = &dl->d_partitions[i]; |
/* skip partitions with no type or outside of slide */ |
if (ppp->p_size == 0 || ppp->p_fstype == 0 || |
(off_t)ppp->p_offset * dl->d_secsize < rawoffset || |
(off_t)(ppp->p_offset + ppp->p_size) * dl->d_secsize |
> (rawoffset + fullsize)) |
useable[i] = 0; |
else |
useable[i] = 1; |
} |
/* Don't munge open partitions. */ |
for (i = 0; i < dl->d_npartitions; i++) { |
if (!useable[i]) |
continue; |
ppp = &dl->d_partitions[i]; |
o = (off_t)ppp->p_offset * dl->d_secsize; |
if (o == 0) |
o = rawoffset; |
error = g_slice_config(gp, i, G_SLICE_CONFIG_CHECK, |
o - rawoffset, (off_t)ppp->p_size * dl->d_secsize, dl->d_secsize, |
"%s%c", gp->name, 'a' + i); |
if (error) |
return (error); |
} |
/* Look good, go for it... */ |
for (u = 0; u < gsp->nslice; u++) { |
if (!useable[u]) |
continue; |
ppp = &dl->d_partitions[u]; |
o = (off_t)ppp->p_offset * dl->d_secsize; |
if (o == 0) |
o = rawoffset; |
g_slice_config(gp, u, G_SLICE_CONFIG_SET, |
o - rawoffset, (off_t)ppp->p_size * dl->d_secsize, dl->d_secsize, |
"%s%c", gp->name, 'a' + u); |
} |
/* Update our softc */ |
ms->rawoffset = rawoffset; |
/* |
* In order to avoid recursively attaching to the same |
* on-disk label (it's usually visible through the 'c' |
* partition) we calculate an MD5 and ask if other BSD's |
* below us love that label. If they do, we don't. |
*/ |
MD5Init(&md5sum); |
MD5Update(&md5sum, ms->label, sizeof(ms->label)); |
MD5Final(ms->labelsum, &md5sum); |
return (0); |
} |
/* |
* This is an internal helper function, called multiple times from the taste |
* function to try to locate a disklabel on the disk. More civilized formats |
* will not need this, as there is only one possible place on disk to look |
* for the magic spot. |
*/ |
static int |
g_nbsd_try(struct g_geom *gp, struct g_slicer *gsp, struct g_consumer *cp, |
int secsize, struct g_nbsd_softc *ms, off_t offset) |
{ |
int error; |
u_char *buf; |
struct disklabel *dl; |
off_t secoff; |
/* |
* We need to read entire aligned sectors, and we assume that the |
* disklabel does not span sectors, so one sector is enough. |
*/ |
error = 0; |
secoff = offset % secsize; |
buf = g_read_data(cp, offset - secoff, secsize, &error); |
if (buf == NULL || error != 0) |
return (ENOENT); |
/* Decode into our native format. */ |
dl = &ms->ondisk; |
error = nbsd_disklabel_le_dec(buf + secoff, dl, NBSD_MAXPARTITIONS); |
/* do not recognize slices which will be recognized by geom_bsd module */ |
if (!error) |
if (ms->mbrtype == MBR_FREEBSD && |
dl->d_npartitions <= FREEBSD_MAXPARTITIONS) |
error = EINVAL; |
if (!error) |
bcopy(buf + secoff, ms->label, LABELSIZE); |
/* Remember to free the buffer g_read_data() gave us. */ |
g_free(buf); |
ms->labeloffset = offset; |
return (error); |
} |
/*- |
* This start routine is only called for non-trivial requests, all the |
* trivial ones are handled autonomously by the slice code. |
* For requests we handle here, we must call the g_io_deliver() on the |
* bio, and return non-zero to indicate to the slice code that we did so. |
* This code executes in the "DOWN" I/O path, this means: |
* * No sleeping. |
* * Don't grab the topology lock. |
* * Don't call biowait, g_getattr(), g_setattr() or g_read_data() |
*/ |
static int |
g_nbsd_ioctl(struct g_provider *pp, u_long cmd, void *data, int fflag, struct thread *td) |
{ |
return (ENOIOCTL); |
} |
static int |
g_nbsd_start(struct bio *bp) |
{ |
struct g_geom *gp; |
struct g_nbsd_softc *ms; |
struct g_slicer *gsp; |
gp = bp->bio_to->geom; |
gsp = gp->softc; |
ms = gsp->softc; |
if (bp->bio_cmd == BIO_GETATTR) { |
if (g_handleattr(bp, "NBSD::labelsum", ms->labelsum, |
sizeof(ms->labelsum))) |
return (1); |
} |
return (0); |
} |
/* |
* Dump configuration information in XML format. |
* Notice that the function is called once for the geom and once for each |
* consumer and provider. We let g_slice_dumpconf() do most of the work. |
*/ |
static void |
g_nbsd_dumpconf(struct sbuf *sb, const char *indent, struct g_geom *gp, |
struct g_consumer *cp, struct g_provider *pp) |
{ |
struct g_nbsd_softc *ms; |
struct g_slicer *gsp; |
gsp = gp->softc; |
ms = gsp->softc; |
g_slice_dumpconf(sb, indent, gp, cp, pp); |
if (indent != NULL && pp == NULL && cp == NULL) { |
sbuf_printf(sb, "%s<labeloffset>%jd</labeloffset>\n", |
indent, (intmax_t)ms->labeloffset); |
sbuf_printf(sb, "%s<rawoffset>%jd</rawoffset>\n", |
indent, (intmax_t)ms->rawoffset); |
sbuf_printf(sb, "%s<mbroffset>%jd</mbroffset>\n", |
indent, (intmax_t)ms->mbroffset); |
} else if (pp != NULL) { |
if (indent == NULL) |
sbuf_printf(sb, " ty %d", |
ms->ondisk.d_partitions[pp->index].p_fstype); |
else |
sbuf_printf(sb, "%s<type>%d</type>\n", indent, |
ms->ondisk.d_partitions[pp->index].p_fstype); |
} |
} |
/* |
* The taste function is called from the event-handler, with the topology |
* lock already held and a provider to examine. The flags are unused. |
* |
* If flags == G_TF_NORMAL, the idea is to take a bite of the provider and |
* if we find valid, consistent magic on it, build a geom on it. |
* any magic bits which indicate that we should automatically put a BSD |
* geom on it. |
* |
* There may be cases where the operator would like to put a BSD-geom on |
* providers which do not meet all of the requirements. This can be done |
* by instead passing the G_TF_INSIST flag, which will override these |
* checks. |
* |
* The final flags value is G_TF_TRANSPARENT, which instructs the method |
* to put a geom on top of the provider and configure it to be as transparent |
* as possible. This is not really relevant to the BSD method and therefore |
* not implemented here. |
*/ |
static struct g_geom * |
g_nbsd_taste(struct g_class *mp, struct g_provider *pp, int flags) |
{ |
MD5_CTX md5sum; |
u_char hash[16]; |
struct g_geom *gp; |
struct g_consumer *cp; |
struct g_nbsd_softc *ms; |
struct g_slicer *gsp; |
int error; |
u_int secsize; |
g_trace(G_T_TOPOLOGY, "nbsd_taste(%s,%s)", mp->name, pp->name); |
g_topology_assert(); |
/* We don't implement transparent inserts. */ |
if (flags == G_TF_TRANSPARENT) |
return (NULL); |
/* |
* BSD labels are a subclass of the general "slicing" topology so |
* a lot of the work can be done by the common "slice" code. |
* Create a geom with space for NBSD_MAXPARTITIONS providers, one consumer |
* and a softc structure for us. Specify the provider to attach |
* the consumer to and our "start" routine for special requests. |
* The provider is opened with mode (1,0,0) so we can do reads |
* from it. |
*/ |
gp = g_slice_new(mp, NBSD_MAXPARTITIONS, pp, &cp, &ms, |
sizeof(*ms), g_nbsd_start); |
if (gp == NULL) |
return (NULL); |
/* Get the geom_slicer softc from the geom. */ |
gsp = gp->softc; |
/* |
* The do...while loop here allows us to have multiple escapes |
* using a simple "break". This improves code clarity without |
* ending up in deep nesting and without using goto or come from. |
*/ |
do { |
/* |
* If the provider is an MBR we will only auto attach |
* to type 165|166|169 slices in the G_TF_NORMAL case. We will |
* attach to any other type. |
*/ |
error = g_getattr("MBR::type", cp, &ms->mbrtype); |
if (!error) { |
if (ms->mbrtype != MBR_OPENBSD && ms->mbrtype != MBR_NETBSD && |
ms->mbrtype != MBR_FREEBSD && flags == G_TF_NORMAL) |
break; |
error = g_getattr("MBR::offset", cp, &ms->mbroffset); |
if (error) |
break; |
} |
/* Same thing if we are inside a PC98 */ |
/* XXX not implemented */ |
/* Get sector size, we need it to read data. */ |
secsize = cp->provider->sectorsize; |
if (secsize < 512) |
break; |
/* First look for a label at the start of the second sector. */ |
error = g_nbsd_try(gp, gsp, cp, secsize, ms, secsize); |
/* If we didn't find a label, punt. */ |
if (error) |
break; |
/* |
* In order to avoid recursively attaching to the same |
* on-disk label (it's usually visible through the 'c' |
* partition) we calculate an MD5 and ask if other BSD's |
* below us love that label. If they do, we don't. |
*/ |
MD5Init(&md5sum); |
MD5Update(&md5sum, ms->label, sizeof(ms->label)); |
MD5Final(ms->labelsum, &md5sum); |
error = g_getattr("NBSD::labelsum", cp, &hash); |
if (!error && !bcmp(ms->labelsum, hash, sizeof(hash))) |
break; |
/* |
* Process the found disklabel, and modify our "slice" |
* instance to match it, if possible. |
*/ |
error = g_nbsd_modify(gp, ms); |
} while (0); |
/* Success or failure, we can close our provider now. */ |
g_access(cp, -1, 0, 0); |
/* If we have configured any providers, return the new geom. */ |
if (gsp->nprovider > 0) { |
g_slice_conf_hot(gp, 0, ms->labeloffset, LABELSIZE, |
G_SLICE_HOT_ALLOW, G_SLICE_HOT_DENY, G_SLICE_HOT_CALL); |
return (gp); |
} |
/* |
* ...else push the "self-destruct" button, by spoiling our own |
* consumer. This triggers a call to g_slice_spoiled which will |
* dismantle what was setup. |
*/ |
g_slice_spoiled(cp); |
return (NULL); |
} |
/* |
* NB! curthread is user process which GCTL'ed. |
*/ |
static void |
g_nbsd_config(struct gctl_req *req, struct g_class *mp, char const *verb) |
{ |
struct g_geom *gp; |
struct g_slicer *gsp; |
struct g_consumer *cp; |
struct g_nbsd_softc *ms; |
g_topology_assert(); |
gp = gctl_get_geom(req, mp, "geom"); |
if (gp == NULL) |
return; |
cp = LIST_FIRST(&gp->consumer); |
gsp = gp->softc; |
ms = gsp->softc; |
if (!strcmp(verb, "read mbroffset")) { |
gctl_set_param(req, "mbroffset", |
&ms->mbroffset, sizeof(ms->mbroffset)); |
return; |
} else { |
gctl_error(req, "Unknown verb parameter"); |
} |
return; |
} |
/* Finally, register with GEOM infrastructure. */ |
static struct g_class g_nbsd_class = { |
.name = NBSD_CLASS_NAME, |
.version = G_VERSION, |
.taste = g_nbsd_taste, |
.ctlreq = g_nbsd_config, |
.dumpconf = g_nbsd_dumpconf, |
.ioctl = g_nbsd_ioctl |
}; |
DECLARE_GEOM_CLASS(g_nbsd_class, g_nbsd); |
//freebsd/geom_nbsd/tags/0001-first-public/src/geom_nbsd_enc.c |
---|
0,0 → 1,136 |
/*- |
* Copyright 2005, Anatoli Klassen <anatoli@aksoft.net> |
* All rights reserved. |
* |
* The code is based on code of geom_bsd module by Poul-Henning Kamp. |
* |
* Copyright (c) 2002 Poul-Henning Kamp |
* Copyright (c) 2002 Networks Associates Technology, Inc. |
* All rights reserved. |
* |
* This software was developed for the FreeBSD Project by Poul-Henning Kamp |
* and NAI Labs, the Security Research Division of Network Associates, Inc. |
* under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the |
* DARPA CHATS research program. |
* |
* 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. |
*/ |
/* |
* Functions to decode struct disklabel and struct partition into |
* a bytestream of little endianess and correct packing. |
*/ |
#include <sys/cdefs.h> |
#include <sys/types.h> |
#include <sys/endian.h> |
#include <sys/errno.h> |
#include <sys/systm.h> |
#include "disklabel.h" |
void |
nbsd_partition_le_dec(u_char *ptr, struct partition *d) |
{ |
d->p_size = le32dec(ptr + 0); |
d->p_offset = le32dec(ptr + 4); |
d->p_fsize = le32dec(ptr + 8); |
d->p_fstype = ptr[12]; |
d->p_frag = ptr[13]; |
d->p_cpg = le16dec(ptr + 14); |
} |
int |
nbsd_disklabel_le_dec(u_char *ptr, struct disklabel *d, int maxpart) |
{ |
int i; |
u_char *p, *pe; |
uint16_t sum; |
d->d_magic = le32dec(ptr + 0); |
if (d->d_magic != DISKMAGIC) |
return (EINVAL); |
d->d_magic2 = le32dec(ptr + 132); |
if (d->d_magic2 != DISKMAGIC) { |
return (EINVAL); |
} |
d->d_npartitions = le16dec(ptr + 138); |
if (maxpart > NBSD_MAXPARTITIONS) { |
return (EINVAL); |
} |
if (d->d_npartitions > maxpart) { |
return (EINVAL); |
} |
pe = ptr + 148 + 16 * d->d_npartitions; |
sum = 0; |
for (p = ptr; p < pe; p += 2) |
sum ^= le16dec(p); |
if (sum != 0) { |
return (EINVAL); |
} |
d->d_type = le16dec(ptr + 4); |
d->d_subtype = le16dec(ptr + 6); |
bcopy(ptr + 8, d->d_typename, 16); |
bcopy(ptr + 24, d->d_packname, 16); |
d->d_secsize = le32dec(ptr + 40); |
d->d_nsectors = le32dec(ptr + 44); |
d->d_ntracks = le32dec(ptr + 48); |
d->d_ncylinders = le32dec(ptr + 52); |
d->d_secpercyl = le32dec(ptr + 56); |
d->d_secperunit = le32dec(ptr + 60); |
d->d_sparespertrack = le16dec(ptr + 64); |
d->d_sparespercyl = le16dec(ptr + 66); |
d->d_acylinders = le32dec(ptr + 68); |
d->d_rpm = le16dec(ptr + 72); |
d->d_interleave = le16dec(ptr + 74); |
d->d_trackskew = le16dec(ptr + 76); |
d->d_cylskew = le16dec(ptr + 78); |
d->d_headswitch = le32dec(ptr + 80); |
d->d_trkseek = le32dec(ptr + 84); |
d->d_flags = le32dec(ptr + 88); |
d->d_drivedata[0] = le32dec(ptr + 92); |
d->d_drivedata[1] = le32dec(ptr + 96); |
d->d_drivedata[2] = le32dec(ptr + 100); |
d->d_drivedata[3] = le32dec(ptr + 104); |
d->d_drivedata[4] = le32dec(ptr + 108); |
d->d_spare[0] = le32dec(ptr + 112); |
d->d_spare[1] = le32dec(ptr + 116); |
d->d_spare[2] = le32dec(ptr + 120); |
d->d_spare[3] = le32dec(ptr + 124); |
d->d_spare[4] = le32dec(ptr + 128); |
d->d_checksum = le16dec(ptr + 136); |
d->d_npartitions = le16dec(ptr + 138); |
d->d_bbsize = le32dec(ptr + 140); |
d->d_sbsize = le32dec(ptr + 144); |
for (i = 0; i < d->d_npartitions; i++) |
nbsd_partition_le_dec(ptr + 148 + 16 * i, &d->d_partitions[i]); |
return (0); |
} |
//freebsd/geom_nbsd/tags/0001-first-public/src/Makefile |
---|
0,0 → 1,6 |
.PATH: . |
KMOD= geom_nbsd |
SRCS= disklabel.h geom_nbsd.c geom_nbsd_enc.c |
.include <bsd.kmod.mk> |
//freebsd/geom_nbsd/tags/0001-first-public/src/disklabel.h |
---|
0,0 → 1,156 |
/*- |
* Copyright 2005, Anatoli Klassen <anatoli@aksoft.net> |
* All rights reserved. |
* |
* The code is based on code of geom_bsd module by Poul-Henning Kamp. |
* |
* Copyright (c) 1987, 1988, 1993 |
* The Regents of the University of California. 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. |
* 4. Neither the name of the University nor the names of its contributors |
* may be used to endorse or promote products derived from this software |
* without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. |
* |
* @(#)disklabel.h 8.2 (Berkeley) 7/10/94 |
*/ |
#ifndef _NBSD_DISKLABEL_H_ |
#define _NBSD_DISKLABEL_H_ |
/* |
* Each disk has a label which includes information about the hardware |
* disk geometry, filesystem partitions, and drive specific information. |
* The label is in block 0 or 1, possibly offset from the beginning |
* to leave room for a bootstrap, etc. |
*/ |
/* XXX these should be defined per controller (or drive) elsewhere, not here! */ |
#if defined(__i386__) || defined(__amd64__) || defined(__arm__) || \ |
defined(__ia64__) |
#define LABELSECTOR 1 /* sector containing label */ |
#define LABELOFFSET 0 /* offset of label in sector */ |
#endif |
#ifdef __alpha__ |
#define LABELSECTOR 0 |
#define LABELOFFSET 64 |
#endif |
#define DISKMAGIC ((u_int32_t)0x82564557) /* The disk magic number */ |
#define FREEBSD_MAXPARTITIONS 8 /* == MAXPARTITIONS in <sys/disklabel.h> */ |
#define NBSD_MAXPARTITIONS 16 |
#define MBR_FREEBSD 0xA5 |
#define MBR_OPENBSD 0xA6 |
#define MBR_NETBSD 0xA9 |
/* Size of bootblock area in sector-size neutral bytes */ |
#define BBSIZE 8192 |
struct disklabel { |
u_int32_t d_magic; /* the magic number */ |
u_int16_t d_type; /* drive type */ |
u_int16_t d_subtype; /* controller/d_type specific */ |
char d_typename[16]; /* type name, e.g. "eagle" */ |
char d_packname[16]; /* pack identifier */ |
/* disk geometry: */ |
u_int32_t d_secsize; /* # of bytes per sector */ |
u_int32_t d_nsectors; /* # of data sectors per track */ |
u_int32_t d_ntracks; /* # of tracks per cylinder */ |
u_int32_t d_ncylinders; /* # of data cylinders per unit */ |
u_int32_t d_secpercyl; /* # of data sectors per cylinder */ |
u_int32_t d_secperunit; /* # of data sectors per unit */ |
/* |
* Spares (bad sector replacements) below are not counted in |
* d_nsectors or d_secpercyl. Spare sectors are assumed to |
* be physical sectors which occupy space at the end of each |
* track and/or cylinder. |
*/ |
u_int16_t d_sparespertrack; /* # of spare sectors per track */ |
u_int16_t d_sparespercyl; /* # of spare sectors per cylinder */ |
/* |
* Alternate cylinders include maintenance, replacement, configuration |
* description areas, etc. |
*/ |
u_int32_t d_acylinders; /* # of alt. cylinders per unit */ |
/* hardware characteristics: */ |
/* |
* d_interleave, d_trackskew and d_cylskew describe perturbations |
* in the media format used to compensate for a slow controller. |
* Interleave is physical sector interleave, set up by the |
* formatter or controller when formatting. When interleaving is |
* in use, logically adjacent sectors are not physically |
* contiguous, but instead are separated by some number of |
* sectors. It is specified as the ratio of physical sectors |
* traversed per logical sector. Thus an interleave of 1:1 |
* implies contiguous layout, while 2:1 implies that logical |
* sector 0 is separated by one sector from logical sector 1. |
* d_trackskew is the offset of sector 0 on track N relative to |
* sector 0 on track N-1 on the same cylinder. Finally, d_cylskew |
* is the offset of sector 0 on cylinder N relative to sector 0 |
* on cylinder N-1. |
*/ |
u_int16_t d_rpm; /* rotational speed */ |
u_int16_t d_interleave; /* hardware sector interleave */ |
u_int16_t d_trackskew; /* sector 0 skew, per track */ |
u_int16_t d_cylskew; /* sector 0 skew, per cylinder */ |
u_int32_t d_headswitch; /* head switch time, usec */ |
u_int32_t d_trkseek; /* track-to-track seek, usec */ |
u_int32_t d_flags; /* generic flags */ |
#define NDDATA 5 |
u_int32_t d_drivedata[NDDATA]; /* drive-type specific information */ |
#define NSPARE 5 |
u_int32_t d_spare[NSPARE]; /* reserved for future use */ |
u_int32_t d_magic2; /* the magic number (again) */ |
u_int16_t d_checksum; /* xor of data incl. partitions */ |
/* filesystem and partition information: */ |
u_int16_t d_npartitions; /* number of partitions in following */ |
u_int32_t d_bbsize; /* size of boot area at sn0, bytes */ |
u_int32_t d_sbsize; /* max size of fs superblock, bytes */ |
struct partition { /* the partition table */ |
u_int32_t p_size; /* number of sectors in partition */ |
u_int32_t p_offset; /* starting sector */ |
u_int32_t p_fsize; /* filesystem basic fragment size */ |
u_int8_t p_fstype; /* filesystem type, see below */ |
u_int8_t p_frag; /* filesystem fragments per block */ |
u_int16_t p_cpg; /* filesystem cylinders per group */ |
} d_partitions[NBSD_MAXPARTITIONS]; /* actually may be more */ |
}; |
#ifdef CTASSERT |
CTASSERT(sizeof(struct disklabel) == 148 + NBSD_MAXPARTITIONS * 16); |
#endif |
/* |
* Functions for proper encoding/decoding of struct disklabel into/from |
* bytestring. |
*/ |
void nbsd_partition_le_dec(u_char *ptr, struct partition *d); |
int nbsd_disklabel_le_dec(u_char *ptr, struct disklabel *d, int maxpart); |
#endif /* !_NBSD_DISKLABEL_H_ */ |
//freebsd/geom_nbsd/trunk/src/geom_nbsd.c |
---|
0,0 → 1,457 |
/*- |
* Copyright 2005, Anatoli Klassen <anatoli@aksoft.net> |
* All rights reserved. |
* |
* The code is based on code of geom_bsd module by Poul-Henning Kamp. |
* |
* Copyright (c) 2002 Poul-Henning Kamp |
* Copyright (c) 2002 Networks Associates Technology, Inc. |
* All rights reserved. |
* |
* This software was developed for the FreeBSD Project by Poul-Henning Kamp |
* and NAI Labs, the Security Research Division of Network Associates, Inc. |
* under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the |
* DARPA CHATS research program. |
* |
* 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. |
*/ |
/* |
* This is the method for dealing with BSD disklabels. It has been |
* extensively (by my standards at least) commented, in the vain hope that |
* it will serve as the source in future copy&paste operations. |
*/ |
#include <sys/param.h> |
#include <sys/systm.h> |
#include <sys/kernel.h> |
#include <sys/bio.h> |
#include <sys/malloc.h> |
#include <sys/lock.h> |
#include <sys/md5.h> |
#include <sys/errno.h> |
#include <geom/geom.h> |
#include <geom/geom_slice.h> |
#include "disklabel.h" |
#define NBSD_CLASS_NAME "NetBSD" |
#define LABELSIZE (148 + 16 * NBSD_MAXPARTITIONS) |
/* |
* Our private data about one instance. All the rest is handled by the |
* slice code and stored in its softc, so this is just the stuff |
* specific to BSD disklabels. |
*/ |
struct g_nbsd_softc { |
int mbrtype; |
off_t labeloffset; |
off_t mbroffset; |
off_t rawoffset; |
struct disklabel ondisk; |
u_char label[LABELSIZE]; |
u_char labelsum[16]; |
}; |
/* |
* Modify our slicer to match proposed disklabel, if possible. |
* This is where we make sure we don't do something stupid. |
*/ |
static int |
g_nbsd_modify(struct g_geom *gp, struct g_nbsd_softc *ms) |
{ |
char useable[NBSD_MAXPARTITIONS]; |
MD5_CTX md5sum; |
struct partition *ppp; |
struct g_slicer *gsp; |
struct g_consumer *cp; |
struct disklabel *dl; |
off_t rawoffset, fullsize, o; |
int i, error; |
u_int secsize, u; |
g_topology_assert(); |
gsp = gp->softc; |
dl = &ms->ondisk; |
/* Get dimensions of our device. */ |
cp = LIST_FIRST(&gp->consumer); |
secsize = cp->provider->sectorsize; |
/* ... or a smaller sector size. */ |
if (dl->d_secsize < secsize) { |
return (EINVAL); |
} |
/* ... or a non-multiple sector size. */ |
if (dl->d_secsize % secsize != 0) { |
return (EINVAL); |
} |
rawoffset = ms->mbroffset; |
fullsize = cp->provider->mediasize; |
for (i = 0; i < dl->d_npartitions; i++) { |
ppp = &dl->d_partitions[i]; |
/* skip partitions with no type or outside of slide */ |
if (ppp->p_size == 0 || ppp->p_fstype == 0 || |
(off_t)ppp->p_offset * dl->d_secsize < rawoffset || |
(off_t)(ppp->p_offset + ppp->p_size) * dl->d_secsize |
> (rawoffset + fullsize)) |
useable[i] = 0; |
else |
useable[i] = 1; |
} |
/* Don't munge open partitions. */ |
for (i = 0; i < dl->d_npartitions; i++) { |
if (!useable[i]) |
continue; |
ppp = &dl->d_partitions[i]; |
o = (off_t)ppp->p_offset * dl->d_secsize; |
if (o == 0) |
o = rawoffset; |
error = g_slice_config(gp, i, G_SLICE_CONFIG_CHECK, |
o - rawoffset, (off_t)ppp->p_size * dl->d_secsize, dl->d_secsize, |
"%s%c", gp->name, 'a' + i); |
if (error) |
return (error); |
} |
/* Look good, go for it... */ |
for (u = 0; u < gsp->nslice; u++) { |
if (!useable[u]) |
continue; |
ppp = &dl->d_partitions[u]; |
o = (off_t)ppp->p_offset * dl->d_secsize; |
if (o == 0) |
o = rawoffset; |
g_slice_config(gp, u, G_SLICE_CONFIG_SET, |
o - rawoffset, (off_t)ppp->p_size * dl->d_secsize, dl->d_secsize, |
"%s%c", gp->name, 'a' + u); |
} |
/* Update our softc */ |
ms->rawoffset = rawoffset; |
/* |
* In order to avoid recursively attaching to the same |
* on-disk label (it's usually visible through the 'c' |
* partition) we calculate an MD5 and ask if other BSD's |
* below us love that label. If they do, we don't. |
*/ |
MD5Init(&md5sum); |
MD5Update(&md5sum, ms->label, sizeof(ms->label)); |
MD5Final(ms->labelsum, &md5sum); |
return (0); |
} |
/* |
* This is an internal helper function, called multiple times from the taste |
* function to try to locate a disklabel on the disk. More civilized formats |
* will not need this, as there is only one possible place on disk to look |
* for the magic spot. |
*/ |
static int |
g_nbsd_try(struct g_geom *gp, struct g_slicer *gsp, struct g_consumer *cp, |
int secsize, struct g_nbsd_softc *ms, off_t offset) |
{ |
int error; |
u_char *buf; |
struct disklabel *dl; |
off_t secoff; |
/* |
* We need to read entire aligned sectors, and we assume that the |
* disklabel does not span sectors, so one sector is enough. |
*/ |
error = 0; |
secoff = offset % secsize; |
buf = g_read_data(cp, offset - secoff, secsize, &error); |
if (buf == NULL || error != 0) |
return (ENOENT); |
/* Decode into our native format. */ |
dl = &ms->ondisk; |
error = nbsd_disklabel_le_dec(buf + secoff, dl, NBSD_MAXPARTITIONS); |
/* do not recognize slices which will be recognized by geom_bsd module */ |
if (!error) |
if (ms->mbrtype == MBR_FREEBSD && |
dl->d_npartitions <= FREEBSD_MAXPARTITIONS) |
error = EINVAL; |
if (!error) |
bcopy(buf + secoff, ms->label, LABELSIZE); |
/* Remember to free the buffer g_read_data() gave us. */ |
g_free(buf); |
ms->labeloffset = offset; |
return (error); |
} |
/*- |
* This start routine is only called for non-trivial requests, all the |
* trivial ones are handled autonomously by the slice code. |
* For requests we handle here, we must call the g_io_deliver() on the |
* bio, and return non-zero to indicate to the slice code that we did so. |
* This code executes in the "DOWN" I/O path, this means: |
* * No sleeping. |
* * Don't grab the topology lock. |
* * Don't call biowait, g_getattr(), g_setattr() or g_read_data() |
*/ |
static int |
g_nbsd_ioctl(struct g_provider *pp, u_long cmd, void *data, int fflag, struct thread *td) |
{ |
return (ENOIOCTL); |
} |
static int |
g_nbsd_start(struct bio *bp) |
{ |
struct g_geom *gp; |
struct g_nbsd_softc *ms; |
struct g_slicer *gsp; |
gp = bp->bio_to->geom; |
gsp = gp->softc; |
ms = gsp->softc; |
if (bp->bio_cmd == BIO_GETATTR) { |
if (g_handleattr(bp, "NBSD::labelsum", ms->labelsum, |
sizeof(ms->labelsum))) |
return (1); |
} |
return (0); |
} |
/* |
* Dump configuration information in XML format. |
* Notice that the function is called once for the geom and once for each |
* consumer and provider. We let g_slice_dumpconf() do most of the work. |
*/ |
static void |
g_nbsd_dumpconf(struct sbuf *sb, const char *indent, struct g_geom *gp, |
struct g_consumer *cp, struct g_provider *pp) |
{ |
struct g_nbsd_softc *ms; |
struct g_slicer *gsp; |
gsp = gp->softc; |
ms = gsp->softc; |
g_slice_dumpconf(sb, indent, gp, cp, pp); |
if (indent != NULL && pp == NULL && cp == NULL) { |
sbuf_printf(sb, "%s<labeloffset>%jd</labeloffset>\n", |
indent, (intmax_t)ms->labeloffset); |
sbuf_printf(sb, "%s<rawoffset>%jd</rawoffset>\n", |
indent, (intmax_t)ms->rawoffset); |
sbuf_printf(sb, "%s<mbroffset>%jd</mbroffset>\n", |
indent, (intmax_t)ms->mbroffset); |
} else if (pp != NULL) { |
if (indent == NULL) |
sbuf_printf(sb, " ty %d", |
ms->ondisk.d_partitions[pp->index].p_fstype); |
else |
sbuf_printf(sb, "%s<type>%d</type>\n", indent, |
ms->ondisk.d_partitions[pp->index].p_fstype); |
} |
} |
/* |
* The taste function is called from the event-handler, with the topology |
* lock already held and a provider to examine. The flags are unused. |
* |
* If flags == G_TF_NORMAL, the idea is to take a bite of the provider and |
* if we find valid, consistent magic on it, build a geom on it. |
* any magic bits which indicate that we should automatically put a BSD |
* geom on it. |
* |
* There may be cases where the operator would like to put a BSD-geom on |
* providers which do not meet all of the requirements. This can be done |
* by instead passing the G_TF_INSIST flag, which will override these |
* checks. |
* |
* The final flags value is G_TF_TRANSPARENT, which instructs the method |
* to put a geom on top of the provider and configure it to be as transparent |
* as possible. This is not really relevant to the BSD method and therefore |
* not implemented here. |
*/ |
static struct g_geom * |
g_nbsd_taste(struct g_class *mp, struct g_provider *pp, int flags) |
{ |
MD5_CTX md5sum; |
u_char hash[16]; |
struct g_geom *gp; |
struct g_consumer *cp; |
struct g_nbsd_softc *ms; |
struct g_slicer *gsp; |
int error; |
u_int secsize; |
g_trace(G_T_TOPOLOGY, "nbsd_taste(%s,%s)", mp->name, pp->name); |
g_topology_assert(); |
/* We don't implement transparent inserts. */ |
if (flags == G_TF_TRANSPARENT) |
return (NULL); |
/* |
* BSD labels are a subclass of the general "slicing" topology so |
* a lot of the work can be done by the common "slice" code. |
* Create a geom with space for NBSD_MAXPARTITIONS providers, one consumer |
* and a softc structure for us. Specify the provider to attach |
* the consumer to and our "start" routine for special requests. |
* The provider is opened with mode (1,0,0) so we can do reads |
* from it. |
*/ |
gp = g_slice_new(mp, NBSD_MAXPARTITIONS, pp, &cp, &ms, |
sizeof(*ms), g_nbsd_start); |
if (gp == NULL) |
return (NULL); |
/* Get the geom_slicer softc from the geom. */ |
gsp = gp->softc; |
/* |
* The do...while loop here allows us to have multiple escapes |
* using a simple "break". This improves code clarity without |
* ending up in deep nesting and without using goto or come from. |
*/ |
do { |
/* |
* If the provider is an MBR we will only auto attach |
* to type 165|166|169 slices in the G_TF_NORMAL case. We will |
* attach to any other type. |
*/ |
error = g_getattr("MBR::type", cp, &ms->mbrtype); |
if (!error) { |
if (ms->mbrtype != MBR_OPENBSD && ms->mbrtype != MBR_NETBSD && |
ms->mbrtype != MBR_FREEBSD && flags == G_TF_NORMAL) |
break; |
error = g_getattr("MBR::offset", cp, &ms->mbroffset); |
if (error) |
break; |
} |
/* Same thing if we are inside a PC98 */ |
/* XXX not implemented */ |
/* Get sector size, we need it to read data. */ |
secsize = cp->provider->sectorsize; |
if (secsize < 512) |
break; |
/* First look for a label at the start of the second sector. */ |
error = g_nbsd_try(gp, gsp, cp, secsize, ms, secsize); |
/* If we didn't find a label, punt. */ |
if (error) |
break; |
/* |
* In order to avoid recursively attaching to the same |
* on-disk label (it's usually visible through the 'c' |
* partition) we calculate an MD5 and ask if other BSD's |
* below us love that label. If they do, we don't. |
*/ |
MD5Init(&md5sum); |
MD5Update(&md5sum, ms->label, sizeof(ms->label)); |
MD5Final(ms->labelsum, &md5sum); |
error = g_getattr("NBSD::labelsum", cp, &hash); |
if (!error && !bcmp(ms->labelsum, hash, sizeof(hash))) |
break; |
/* |
* Process the found disklabel, and modify our "slice" |
* instance to match it, if possible. |
*/ |
error = g_nbsd_modify(gp, ms); |
} while (0); |
/* Success or failure, we can close our provider now. */ |
g_access(cp, -1, 0, 0); |
/* If we have configured any providers, return the new geom. */ |
if (gsp->nprovider > 0) { |
g_slice_conf_hot(gp, 0, ms->labeloffset, LABELSIZE, |
G_SLICE_HOT_ALLOW, G_SLICE_HOT_DENY, G_SLICE_HOT_CALL); |
return (gp); |
} |
/* |
* ...else push the "self-destruct" button, by spoiling our own |
* consumer. This triggers a call to g_slice_spoiled which will |
* dismantle what was setup. |
*/ |
g_slice_spoiled(cp); |
return (NULL); |
} |
/* |
* NB! curthread is user process which GCTL'ed. |
*/ |
static void |
g_nbsd_config(struct gctl_req *req, struct g_class *mp, char const *verb) |
{ |
struct g_geom *gp; |
struct g_slicer *gsp; |
struct g_consumer *cp; |
struct g_nbsd_softc *ms; |
g_topology_assert(); |
gp = gctl_get_geom(req, mp, "geom"); |
if (gp == NULL) |
return; |
cp = LIST_FIRST(&gp->consumer); |
gsp = gp->softc; |
ms = gsp->softc; |
if (!strcmp(verb, "read mbroffset")) { |
gctl_set_param(req, "mbroffset", |
&ms->mbroffset, sizeof(ms->mbroffset)); |
return; |
} else { |
gctl_error(req, "Unknown verb parameter"); |
} |
return; |
} |
/* Finally, register with GEOM infrastructure. */ |
static struct g_class g_nbsd_class = { |
.name = NBSD_CLASS_NAME, |
.version = G_VERSION, |
.taste = g_nbsd_taste, |
.ctlreq = g_nbsd_config, |
.dumpconf = g_nbsd_dumpconf, |
.ioctl = g_nbsd_ioctl |
}; |
DECLARE_GEOM_CLASS(g_nbsd_class, g_nbsd); |
//freebsd/geom_nbsd/trunk/src/geom_nbsd_enc.c |
---|
0,0 → 1,136 |
/*- |
* Copyright 2005, Anatoli Klassen <anatoli@aksoft.net> |
* All rights reserved. |
* |
* The code is based on code of geom_bsd module by Poul-Henning Kamp. |
* |
* Copyright (c) 2002 Poul-Henning Kamp |
* Copyright (c) 2002 Networks Associates Technology, Inc. |
* All rights reserved. |
* |
* This software was developed for the FreeBSD Project by Poul-Henning Kamp |
* and NAI Labs, the Security Research Division of Network Associates, Inc. |
* under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the |
* DARPA CHATS research program. |
* |
* 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. |
*/ |
/* |
* Functions to decode struct disklabel and struct partition into |
* a bytestream of little endianess and correct packing. |
*/ |
#include <sys/cdefs.h> |
#include <sys/types.h> |
#include <sys/endian.h> |
#include <sys/errno.h> |
#include <sys/systm.h> |
#include "disklabel.h" |
void |
nbsd_partition_le_dec(u_char *ptr, struct partition *d) |
{ |
d->p_size = le32dec(ptr + 0); |
d->p_offset = le32dec(ptr + 4); |
d->p_fsize = le32dec(ptr + 8); |
d->p_fstype = ptr[12]; |
d->p_frag = ptr[13]; |
d->p_cpg = le16dec(ptr + 14); |
} |
int |
nbsd_disklabel_le_dec(u_char *ptr, struct disklabel *d, int maxpart) |
{ |
int i; |
u_char *p, *pe; |
uint16_t sum; |
d->d_magic = le32dec(ptr + 0); |
if (d->d_magic != DISKMAGIC) |
return (EINVAL); |
d->d_magic2 = le32dec(ptr + 132); |
if (d->d_magic2 != DISKMAGIC) { |
return (EINVAL); |
} |
d->d_npartitions = le16dec(ptr + 138); |
if (maxpart > NBSD_MAXPARTITIONS) { |
return (EINVAL); |
} |
if (d->d_npartitions > maxpart) { |
return (EINVAL); |
} |
pe = ptr + 148 + 16 * d->d_npartitions; |
sum = 0; |
for (p = ptr; p < pe; p += 2) |
sum ^= le16dec(p); |
if (sum != 0) { |
return (EINVAL); |
} |
d->d_type = le16dec(ptr + 4); |
d->d_subtype = le16dec(ptr + 6); |
bcopy(ptr + 8, d->d_typename, 16); |
bcopy(ptr + 24, d->d_packname, 16); |
d->d_secsize = le32dec(ptr + 40); |
d->d_nsectors = le32dec(ptr + 44); |
d->d_ntracks = le32dec(ptr + 48); |
d->d_ncylinders = le32dec(ptr + 52); |
d->d_secpercyl = le32dec(ptr + 56); |
d->d_secperunit = le32dec(ptr + 60); |
d->d_sparespertrack = le16dec(ptr + 64); |
d->d_sparespercyl = le16dec(ptr + 66); |
d->d_acylinders = le32dec(ptr + 68); |
d->d_rpm = le16dec(ptr + 72); |
d->d_interleave = le16dec(ptr + 74); |
d->d_trackskew = le16dec(ptr + 76); |
d->d_cylskew = le16dec(ptr + 78); |
d->d_headswitch = le32dec(ptr + 80); |
d->d_trkseek = le32dec(ptr + 84); |
d->d_flags = le32dec(ptr + 88); |
d->d_drivedata[0] = le32dec(ptr + 92); |
d->d_drivedata[1] = le32dec(ptr + 96); |
d->d_drivedata[2] = le32dec(ptr + 100); |
d->d_drivedata[3] = le32dec(ptr + 104); |
d->d_drivedata[4] = le32dec(ptr + 108); |
d->d_spare[0] = le32dec(ptr + 112); |
d->d_spare[1] = le32dec(ptr + 116); |
d->d_spare[2] = le32dec(ptr + 120); |
d->d_spare[3] = le32dec(ptr + 124); |
d->d_spare[4] = le32dec(ptr + 128); |
d->d_checksum = le16dec(ptr + 136); |
d->d_npartitions = le16dec(ptr + 138); |
d->d_bbsize = le32dec(ptr + 140); |
d->d_sbsize = le32dec(ptr + 144); |
for (i = 0; i < d->d_npartitions; i++) |
nbsd_partition_le_dec(ptr + 148 + 16 * i, &d->d_partitions[i]); |
return (0); |
} |
//freebsd/geom_nbsd/trunk/src/Makefile |
---|
0,0 → 1,6 |
.PATH: . |
KMOD= geom_nbsd |
SRCS= disklabel.h geom_nbsd.c geom_nbsd_enc.c |
.include <bsd.kmod.mk> |
//freebsd/geom_nbsd/trunk/src/disklabel.h |
---|
0,0 → 1,156 |
/*- |
* Copyright 2005, Anatoli Klassen <anatoli@aksoft.net> |
* All rights reserved. |
* |
* The code is based on code of geom_bsd module by Poul-Henning Kamp. |
* |
* Copyright (c) 1987, 1988, 1993 |
* The Regents of the University of California. 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. |
* 4. Neither the name of the University nor the names of its contributors |
* may be used to endorse or promote products derived from this software |
* without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. |
* |
* @(#)disklabel.h 8.2 (Berkeley) 7/10/94 |
*/ |
#ifndef _NBSD_DISKLABEL_H_ |
#define _NBSD_DISKLABEL_H_ |
/* |
* Each disk has a label which includes information about the hardware |
* disk geometry, filesystem partitions, and drive specific information. |
* The label is in block 0 or 1, possibly offset from the beginning |
* to leave room for a bootstrap, etc. |
*/ |
/* XXX these should be defined per controller (or drive) elsewhere, not here! */ |
#if defined(__i386__) || defined(__amd64__) || defined(__arm__) || \ |
defined(__ia64__) |
#define LABELSECTOR 1 /* sector containing label */ |
#define LABELOFFSET 0 /* offset of label in sector */ |
#endif |
#ifdef __alpha__ |
#define LABELSECTOR 0 |
#define LABELOFFSET 64 |
#endif |
#define DISKMAGIC ((u_int32_t)0x82564557) /* The disk magic number */ |
#define FREEBSD_MAXPARTITIONS 8 /* == MAXPARTITIONS in <sys/disklabel.h> */ |
#define NBSD_MAXPARTITIONS 16 |
#define MBR_FREEBSD 0xA5 |
#define MBR_OPENBSD 0xA6 |
#define MBR_NETBSD 0xA9 |
/* Size of bootblock area in sector-size neutral bytes */ |
#define BBSIZE 8192 |
struct disklabel { |
u_int32_t d_magic; /* the magic number */ |
u_int16_t d_type; /* drive type */ |
u_int16_t d_subtype; /* controller/d_type specific */ |
char d_typename[16]; /* type name, e.g. "eagle" */ |
char d_packname[16]; /* pack identifier */ |
/* disk geometry: */ |
u_int32_t d_secsize; /* # of bytes per sector */ |
u_int32_t d_nsectors; /* # of data sectors per track */ |
u_int32_t d_ntracks; /* # of tracks per cylinder */ |
u_int32_t d_ncylinders; /* # of data cylinders per unit */ |
u_int32_t d_secpercyl; /* # of data sectors per cylinder */ |
u_int32_t d_secperunit; /* # of data sectors per unit */ |
/* |
* Spares (bad sector replacements) below are not counted in |
* d_nsectors or d_secpercyl. Spare sectors are assumed to |
* be physical sectors which occupy space at the end of each |
* track and/or cylinder. |
*/ |
u_int16_t d_sparespertrack; /* # of spare sectors per track */ |
u_int16_t d_sparespercyl; /* # of spare sectors per cylinder */ |
/* |
* Alternate cylinders include maintenance, replacement, configuration |
* description areas, etc. |
*/ |
u_int32_t d_acylinders; /* # of alt. cylinders per unit */ |
/* hardware characteristics: */ |
/* |
* d_interleave, d_trackskew and d_cylskew describe perturbations |
* in the media format used to compensate for a slow controller. |
* Interleave is physical sector interleave, set up by the |
* formatter or controller when formatting. When interleaving is |
* in use, logically adjacent sectors are not physically |
* contiguous, but instead are separated by some number of |
* sectors. It is specified as the ratio of physical sectors |
* traversed per logical sector. Thus an interleave of 1:1 |
* implies contiguous layout, while 2:1 implies that logical |
* sector 0 is separated by one sector from logical sector 1. |
* d_trackskew is the offset of sector 0 on track N relative to |
* sector 0 on track N-1 on the same cylinder. Finally, d_cylskew |
* is the offset of sector 0 on cylinder N relative to sector 0 |
* on cylinder N-1. |
*/ |
u_int16_t d_rpm; /* rotational speed */ |
u_int16_t d_interleave; /* hardware sector interleave */ |
u_int16_t d_trackskew; /* sector 0 skew, per track */ |
u_int16_t d_cylskew; /* sector 0 skew, per cylinder */ |
u_int32_t d_headswitch; /* head switch time, usec */ |
u_int32_t d_trkseek; /* track-to-track seek, usec */ |
u_int32_t d_flags; /* generic flags */ |
#define NDDATA 5 |
u_int32_t d_drivedata[NDDATA]; /* drive-type specific information */ |
#define NSPARE 5 |
u_int32_t d_spare[NSPARE]; /* reserved for future use */ |
u_int32_t d_magic2; /* the magic number (again) */ |
u_int16_t d_checksum; /* xor of data incl. partitions */ |
/* filesystem and partition information: */ |
u_int16_t d_npartitions; /* number of partitions in following */ |
u_int32_t d_bbsize; /* size of boot area at sn0, bytes */ |
u_int32_t d_sbsize; /* max size of fs superblock, bytes */ |
struct partition { /* the partition table */ |
u_int32_t p_size; /* number of sectors in partition */ |
u_int32_t p_offset; /* starting sector */ |
u_int32_t p_fsize; /* filesystem basic fragment size */ |
u_int8_t p_fstype; /* filesystem type, see below */ |
u_int8_t p_frag; /* filesystem fragments per block */ |
u_int16_t p_cpg; /* filesystem cylinders per group */ |
} d_partitions[NBSD_MAXPARTITIONS]; /* actually may be more */ |
}; |
#ifdef CTASSERT |
CTASSERT(sizeof(struct disklabel) == 148 + NBSD_MAXPARTITIONS * 16); |
#endif |
/* |
* Functions for proper encoding/decoding of struct disklabel into/from |
* bytestring. |
*/ |
void nbsd_partition_le_dec(u_char *ptr, struct partition *d); |
int nbsd_disklabel_le_dec(u_char *ptr, struct disklabel *d, int maxpart); |
#endif /* !_NBSD_DISKLABEL_H_ */ |