summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorrin <rin@NetBSD.org>2017-02-26 11:56:49 +0000
committerrin <rin@NetBSD.org>2017-02-26 11:56:49 +0000
commit161f4ff9a61ffa9682259a583b4f47663c570dc3 (patch)
treecc1bae73c7c897f1115a9977ec45ee689259139f /sys/dev
parenta814ed5d26cf28d64a041b198d2a24a04637e8f2 (diff)
Add DKWEDGE_METHOD_RDB option, which is Amiga Rigid Disk Block (RDB)
partitioning detection method for dk(4).
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/dkwedge/dkwedge_rdb.c373
-rw-r--r--sys/dev/files.dev3
2 files changed, 375 insertions, 1 deletions
diff --git a/sys/dev/dkwedge/dkwedge_rdb.c b/sys/dev/dkwedge/dkwedge_rdb.c
new file mode 100644
index 00000000000..faef90ab291
--- /dev/null
+++ b/sys/dev/dkwedge/dkwedge_rdb.c
@@ -0,0 +1,373 @@
+/* $NetBSD: dkwedge_rdb.c,v 1.1 2017/02/26 11:56:49 rin Exp $ */
+
+/*
+ * Adapted from arch/amiga/amiga/disksubr.c:
+ *
+ * Copyright (c) 1982, 1986, 1988 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.
+ * 3. 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.
+ *
+ * @(#)ufs_disksubr.c 7.16 (Berkeley) 5/4/91
+ */
+
+/*
+ * Copyright (c) 1994 Christian E. Hopps
+ *
+ * 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 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.
+ *
+ * @(#)ufs_disksubr.c 7.16 (Berkeley) 5/4/91
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: dkwedge_rdb.c,v 1.1 2017/02/26 11:56:49 rin Exp $");
+
+#include <sys/param.h>
+#include <sys/disklabel_rdb.h>
+#include <sys/disk.h>
+#include <sys/endian.h>
+#include <sys/malloc.h>
+#ifdef _KERNEL
+#include <sys/systm.h>
+#endif
+
+/*
+ * In /usr/src/sys/dev/scsipi/sd.c, routine sdstart() adjusts the
+ * block numbers, it changes from DEV_BSIZE units to physical units:
+ * blkno = bp->b_blkno / (lp->d_secsize / DEV_BSIZE);
+ * As long as media with sector sizes of 512 bytes are used, this
+ * doesn't matter (divide by 1), but for successful usage of media with
+ * greater sector sizes (e.g. 640MB MO-media with 2048 bytes/sector)
+ * we must multiply block numbers with (lp->d_secsize / DEV_BSIZE)
+ * to keep "unchanged" physical block numbers.
+ */
+#define SD_C_ADJUSTS_NR
+#ifdef SD_C_ADJUSTS_NR
+#define ADJUST_NR(x) ((x) * (secsize / DEV_BSIZE))
+#else
+#define ADJUST_NR(x) (x)
+#endif
+
+/* XXX */
+#define PARANOID
+
+#ifdef _KERNEL
+#define DKW_MALLOC(SZ) malloc((SZ), M_DEVBUF, M_WAITOK)
+#define DKW_FREE(PTR) free((PTR), M_DEVBUF)
+#define DKW_REALLOC(PTR, NEWSZ) realloc((PTR), (NEWSZ), M_DEVBUF, M_WAITOK)
+#else
+#define DKW_MALLOC(SZ) malloc((SZ))
+#define DKW_FREE(PTR) free((PTR))
+#define DKW_REALLOC(PTR, NEWSZ) realloc((PTR), (NEWSZ))
+#endif
+
+static unsigned rdbchksum(void *);
+static unsigned char getarchtype(unsigned);
+static const char *archtype_to_ptype(unsigned char);
+
+static int
+dkwedge_discover_rdb(struct disk *pdk, struct vnode *vp)
+{
+ struct dkwedge_info dkw;
+ struct partblock *pbp;
+ struct rdblock *rbp;
+ void *bp;
+ int error;
+ unsigned blk_per_cyl, bufsize, nextb, secsize, tabsize;
+ const char *ptype;
+ unsigned char archtype;
+ bool found, root, swap;
+
+ secsize = bufsize = DEV_BSIZE << pdk->dk_blkshift;
+ while (bufsize < sizeof(struct partblock) ||
+ bufsize < sizeof(struct rdblock))
+ bufsize *= 2;
+ bp = DKW_MALLOC(bufsize);
+
+ /*
+ * find the RDB block
+ * XXX bsdlabel should be detected by the other method
+ */
+ for (nextb = 0; nextb < RDB_MAXBLOCKS; nextb++) {
+ error = dkwedge_read(pdk, vp, ADJUST_NR(nextb), bp, bufsize);
+ if (error) {
+ aprint_error("%s: unable to read RDB @ %u, "
+ "error = %d\n", pdk->dk_name, nextb, error);
+ error = ESRCH;
+ goto done;
+ }
+ rbp = (struct rdblock *)bp;
+ if (be32toh(rbp->id) == RDBLOCK_ID) {
+ if (rdbchksum(rbp) == 0)
+ break;
+ else
+ aprint_error("%s: RDB bad checksum @ %u\n",
+ pdk->dk_name, nextb);
+ }
+ }
+
+ if (nextb == RDB_MAXBLOCKS) {
+ error = ESRCH;
+ goto done;
+ }
+
+#ifdef PARANOID
+ unsigned newsecsize = be32toh(rbp->nbytes);
+ if (secsize != newsecsize) {
+ aprint_verbose("secsize changed from %u to %u\n",
+ secsize, newsecsize);
+ secsize = bufsize = newsecsize;
+ while (bufsize < sizeof(struct partblock) ||
+ bufsize < sizeof(struct rdblock))
+ bufsize *= 2;
+ bp = DKW_REALLOC(bp, bufsize);
+ }
+#endif
+
+ strlcpy(dkw.dkw_parent, pdk->dk_name, sizeof(dkw.dkw_parent));
+
+ found = root = swap = false;
+ /*
+ * scan for partition blocks
+ */
+ for (nextb = be32toh(rbp->partbhead); nextb != RDBNULL;
+ nextb = be32toh(pbp->next)) {
+ error = dkwedge_read(pdk, vp, ADJUST_NR(nextb), bp, bufsize);
+ if (error) {
+ aprint_error("%s: unable to read RDB partition block @ "
+ "%u, error = %d\n", pdk->dk_name, nextb, error);
+ error = ESRCH;
+ goto done;
+ }
+ pbp = (struct partblock *)bp;
+
+ if (be32toh(pbp->id) != PARTBLOCK_ID) {
+ aprint_error(
+ "%s: RDB partition block @ %u bad id\n",
+ pdk->dk_name, nextb);
+ error = ESRCH;
+ goto done;
+ }
+ if (rdbchksum(pbp)) {
+ aprint_error(
+ "%s: RDB partition block @ %u bad checksum\n",
+ pdk->dk_name, nextb);
+ error = ESRCH;
+ goto done;
+ }
+
+ tabsize = be32toh(pbp->e.tabsize);
+ if (tabsize < 11) {
+ /*
+ * not enough info, too funky for us.
+ * I don't want to skip I want it fixed.
+ */
+ aprint_error(
+ "%s: RDB partition block @ %u bad partition info "
+ "(environ < 11)\n",
+ pdk->dk_name, nextb);
+ error = ESRCH;
+ goto done;
+ }
+
+ /*
+ * XXXX should be ">" however some vendors don't know
+ * what a table size is so, we hack for them.
+ * the other checks can fail for all I care but this
+ * is a very common value. *sigh*.
+ */
+ if (tabsize >= 16)
+ archtype = getarchtype(be32toh(pbp->e.dostype));
+ else
+ archtype = ADT_UNKNOWN;
+
+ switch (archtype) {
+ case ADT_NETBSDROOT:
+ if (root) {
+ aprint_error("%s: more than one root RDB "
+ "partition, ignoring\n", pdk->dk_name);
+ continue;
+ }
+ root = true;
+ break;
+ case ADT_NETBSDSWAP:
+ if (swap) {
+ aprint_error("%s: more than one swap RDB "
+ "partition , ignoring\n", pdk->dk_name);
+ continue;
+ }
+ swap = true;
+ break;
+ default:
+ break;
+ }
+
+ if (pbp->partname[0] + 1 < sizeof(pbp->partname))
+ pbp->partname[pbp->partname[0] + 1] = 0;
+ else
+ pbp->partname[sizeof(pbp->partname) - 1] = 0;
+ strlcpy(dkw.dkw_wname, pbp->partname + 1,
+ sizeof(dkw.dkw_wname));
+
+ ptype = archtype_to_ptype(archtype);
+ strlcpy(dkw.dkw_ptype, ptype, sizeof(dkw.dkw_ptype));
+
+ blk_per_cyl =
+ be32toh(pbp->e.secpertrk) * be32toh(pbp->e.numheads)
+ * ((be32toh(pbp->e.sizeblock) << 2) / secsize);
+ dkw.dkw_size = (uint64_t)(be32toh(pbp->e.highcyl)
+ - be32toh(pbp->e.lowcyl) + 1) * blk_per_cyl;
+ dkw.dkw_offset = (daddr_t)be32toh(pbp->e.lowcyl) * blk_per_cyl;
+
+ error = dkwedge_add(&dkw);
+ if (error == EEXIST) {
+ aprint_error(
+ "%s: wedge named '%s' already exists, ignoring\n",
+ pdk->dk_name, dkw.dkw_wname);
+ } else if (error)
+ aprint_error("%s: error %d adding partition %s\n",
+ pdk->dk_name, error, dkw.dkw_wname);
+ else
+ found = true;
+ }
+
+ if (found)
+ error = 0;
+ else
+ error = ESRCH;
+done:
+ DKW_FREE(bp);
+ return error;
+}
+
+static unsigned
+rdbchksum(void *bdata)
+{
+ unsigned *blp, cnt, val;
+
+ blp = bdata;
+ cnt = be32toh(blp[1]);
+ val = 0;
+
+ while (cnt--)
+ val += be32toh(*blp++);
+ return(val);
+}
+
+static unsigned char
+getarchtype(unsigned dostype)
+{
+ unsigned t3, b1;
+
+ t3 = dostype & 0xffffff00;
+ b1 = dostype & 0x000000ff;
+
+ switch (t3) {
+ case DOST_NBR:
+ return ADT_NETBSDROOT;
+ case DOST_NBS:
+ return ADT_NETBSDSWAP;
+ case DOST_NBU:
+ return ADT_NETBSDUSER;
+ case DOST_MUFS: /* check for 'muFS'? */
+ case DOST_DOS:
+ return ADT_AMIGADOS;
+ case DOST_AMIX:
+ return ADT_AMIX;
+
+ case DOST_XXXBSD:
+#ifdef DIAGNOSTIC
+ aprint_verbose("deprecated dostype found: 0x%x\n",
+ dostype);
+#endif
+ switch (b1) {
+ case 'R':
+ return ADT_NETBSDROOT;
+ case 'S':
+ return ADT_NETBSDSWAP;
+ default:
+ return ADT_NETBSDUSER;
+ }
+
+ case DOST_EXT2:
+ return ADT_EXT2;
+ case DOST_RAID:
+ return ADT_RAID;
+ default:
+#ifdef DIAGNOSTIC
+ aprint_verbose("warning unknown dostype: 0x%x\n",
+ dostype);
+#endif
+ return ADT_UNKNOWN;
+ }
+}
+
+static const char *
+archtype_to_ptype(unsigned char archtype)
+{
+ switch (archtype) {
+ case ADT_NETBSDROOT:
+ case ADT_NETBSDUSER:
+ return DKW_PTYPE_FFS;
+ case ADT_NETBSDSWAP:
+ return DKW_PTYPE_SWAP;
+ case ADT_AMIGADOS:
+ return DKW_PTYPE_AMIGADOS;
+ case ADT_EXT2:
+ return DKW_PTYPE_EXT2FS;
+ default:
+ return DKW_PTYPE_UNKNOWN;
+ }
+}
+
+#ifdef _KERNEL
+DKWEDGE_DISCOVERY_METHOD_DECL(RDB, 15, dkwedge_discover_rdb);
+#endif
diff --git a/sys/dev/files.dev b/sys/dev/files.dev
index 0e53d67500c..d900e2aa2f0 100644
--- a/sys/dev/files.dev
+++ b/sys/dev/files.dev
@@ -1,4 +1,4 @@
-# $NetBSD: files.dev,v 1.2 2016/12/10 10:26:38 mlelstv Exp $
+# $NetBSD: files.dev,v 1.3 2017/02/26 11:56:49 rin Exp $
file dev/bio.c bio needs-flag
file dev/ccd.c ccd
@@ -12,6 +12,7 @@ file dev/dkwedge/dkwedge_apple.c dkwedge_method_apple
file dev/dkwedge/dkwedge_bsdlabel.c dkwedge_method_bsdlabel
file dev/dkwedge/dkwedge_gpt.c dkwedge_method_gpt
file dev/dkwedge/dkwedge_mbr.c dkwedge_method_mbr
+file dev/dkwedge/dkwedge_rdb.c dkwedge_method_rdb
file dev/firmload.c firmload
file dev/fss.c fss
file dev/keylock.c keylock