summaryrefslogtreecommitdiff
path: root/sys/arch/mips64
diff options
context:
space:
mode:
authorPer Fogelstrom <pefo@cvs.openbsd.org>2004-08-23 14:24:58 +0000
committerPer Fogelstrom <pefo@cvs.openbsd.org>2004-08-23 14:24:58 +0000
commita311b7957d8de9da5b69807d5b6cac213a6744ef (patch)
tree8c4fae19cbf6b64e994f16b30566b35bf4374e20 /sys/arch/mips64
parent734774568039991fce29dd03476f90c2bfaaefcc (diff)
new disklabel for sgi
Diffstat (limited to 'sys/arch/mips64')
-rw-r--r--sys/arch/mips64/include/disklabel.h383
-rw-r--r--sys/arch/mips64/mips64/disksubr.c932
2 files changed, 1115 insertions, 200 deletions
diff --git a/sys/arch/mips64/include/disklabel.h b/sys/arch/mips64/include/disklabel.h
index 8a02db20cfc..d54c41c341d 100644
--- a/sys/arch/mips64/include/disklabel.h
+++ b/sys/arch/mips64/include/disklabel.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: disklabel.h,v 1.1 2004/08/06 20:56:01 pefo Exp $ */
-/* $NetBSD: disklabel.h,v 1.3 1996/03/09 20:52:54 ghudson Exp $ */
+/* $OpenBSD: disklabel.h,v 1.2 2004/08/23 14:24:56 pefo Exp $ */
+/* $NetBSD: disklabel.h,v 1.1 1995/02/13 23:07:34 cgd Exp $ */
/*
* Copyright (c) 1994 Christopher G. Demetriou
@@ -31,18 +31,42 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef _MIPS_DISKLABEL_H_
-#define _MIPS_DISKLABEL_H_
+#ifndef _MACHINE_DISKLABEL_H_
+#define _MACHINE_DISKLABEL_H_
-#define LABELSECTOR 1 /* sector containing label */
-#define LABELOFFSET 0 /* offset of label in sector */
-#define MAXPARTITIONS 16 /* number of partitions */
-#define RAW_PART 2 /* raw partition: ie. rsd0c */
+enum disklabel_tag { DLT_ALPHA, DLT_I386, DLT_AMIGA, DLT_HPPA, DLT_SGI };
+
+/*
+ * What disklabels are we probing for, and in which order?
+ */
+#ifndef LABELPROBES
+#define LABELPROBES DLT_ALPHA, DLT_I386, DLT_AMIGA, DLT_HPPA, DLT_SGI
+#endif
+
+#define ALPHA_LABELSECTOR 0 /* sector containing label */
+#define ALPHA_LABELOFFSET 64 /* offset of label in sector */
+#define I386_LABELSECTOR 1 /* sector containing label */
+#define I386_LABELOFFSET 0 /* offset of label in sector */
+#define AMIGA_LABELSECTOR 0 /* sector containing label */
+#define AMIGA_LABELOFFSET 64 /* offset of label in sector */
+#define HPPA_LABELSECTOR 1 /* sector containing label */
+#define HPPA_LABELOFFSET 0 /* offset of label in sector */
+#define SGI_LABELSECTOR 1 /* sector containing label */
+#define SGI_LABELOFFSET 0 /* offset of label in sector */
+
+#define LABELSECTOR SGI_LABELSECTOR
+#define LABELOFFSET SGI_LABELOFFSET
+
+#define MAXPARTITIONS 16 /* number of partitions */
+#define RAW_PART 2 /* raw partition: xx?c */
/* DOS partition table -- located in boot block */
#define DOSBBSECTOR 0 /* DOS boot block relative sector # */
#define DOSPARTOFF 446
+#define DOSACTIVE 0x80
#define NDOSPART 4
+#define DOSMBR_SIGNATURE 0xaa55
+#define DOSMBR_SIGNATURE_OFF 0x1fe
struct dos_partition {
u_int8_t dp_flag; /* bootstrap flags */
@@ -72,16 +96,343 @@ struct dos_partition {
#define DOSPTYP_OPENBSD 0xa6 /* OpenBSD partition type */
#define DOSPTYP_NETBSD 0xa9 /* NetBSD partition type */
+/* Isolate the relevant bits to get sector and cylinder. */
+#define DPSECT(s) ((s) & 0x3f)
+#define DPCYL(c, s) ((c) + (((s) & 0xc0) << 2))
+
+/*
+ * describes ados Rigid Disk Blocks
+ * which are used to partition a drive
+ */
+#define RDBNULL ((u_int32_t)0xffffffff)
+
+/*
+ * you will find rdblock somewhere in [0, RDBMAXBLOCKS)
+ */
+#define RDB_MAXBLOCKS 16
+
+struct rdblock {
+ u_int32_t id; /* 'RDSK' */
+ u_int32_t nsumlong; /* number of longs in check sum */
+ u_int32_t chksum; /* simple additive with wrap checksum */
+ u_int32_t hostid; /* scsi target of host */
+ u_int32_t nbytes; /* size of disk blocks */
+ u_int32_t flags;
+ u_int32_t badbhead; /* linked list of badblocks */
+ u_int32_t partbhead; /* linked list of partblocks */
+ u_int32_t fsbhead; /* " " of fsblocks */
+ u_int32_t driveinit;
+ u_int32_t resv1[6]; /* RDBNULL */
+ u_int32_t ncylinders; /* number of cylinders on drive */
+ u_int32_t nsectors; /* number of sectors per track */
+ u_int32_t nheads; /* number of tracks per cylinder */
+ u_int32_t interleave;
+ u_int32_t park; /* only used with st506 i.e. not */
+ u_int32_t resv2[3];
+ u_int32_t wprecomp; /* start cyl for write precomp */
+ u_int32_t reducedwrite; /* start cyl for reduced write current */
+ u_int32_t steprate; /* driver step rate in ?s */
+ u_int32_t resv3[5];
+ u_int32_t rdblowb; /* lowblock of range for rdb's */
+ u_int32_t rdbhighb; /* high block of range for rdb's */
+ u_int32_t lowcyl; /* low cylinder of partition area */
+ u_int32_t highcyl; /* upper cylinder of partition area */
+ u_int32_t secpercyl; /* number of sectors per cylinder */
+ u_int32_t parkseconds; /* zero if no park needed */
+ u_int32_t resv4[2];
+ char diskvendor[8]; /* inquiry stuff */
+ char diskproduct[16]; /* inquiry stuff */
+ char diskrevision[4]; /* inquiry stuff */
+ char contvendor[8]; /* inquiry stuff */
+ char contproduct[16]; /* inquiry stuff */
+ char contrevision[4]; /* inquiry stuff */
+#if never_use_secsize
+ u_int32_t resv5[0];
+#endif
+};
+
+
+#define RDBF_LAST 0x1 /* last drive available */
+#define RDBF_LASTLUN 0x2 /* last LUN available */
+#define RDBF_LASTUNIT 0x4 /* last target available */
+#define RDBF_NORESELECT 0x8 /* do not use reselect */
+#define RDBF_DISKID 0x10 /* disk id is valid ?? */
+#define RDBF_CTRLID 0x20 /* ctrl id is valid ?? */
+#define RDBF_SYNC 0x40 /* drive supports SCSI synchronous mode */
+
+struct ados_environ {
+ u_int32_t tabsize; /* 0: environ table size */
+ u_int32_t sizeblock; /* 1: n long words in a block */
+ u_int32_t secorg; /* 2: not used must be zero */
+ u_int32_t numheads; /* 3: number of surfaces */
+ u_int32_t secperblk; /* 4: must be 1 */
+ u_int32_t secpertrk; /* 5: blocks per track */
+ u_int32_t resvblocks; /* 6: reserved blocks at start */
+ u_int32_t prefac; /* 7: must be 0 */
+ u_int32_t interleave; /* 8: normally 1 */
+ u_int32_t lowcyl; /* 9: low cylinder of partition */
+ u_int32_t highcyl; /* 10: upper cylinder of partition */
+ u_int32_t numbufs; /* 11: ados: number of buffers */
+ u_int32_t membuftype; /* 12: ados: type of bufmem */
+ u_int32_t maxtrans; /* 13: maxtrans the ctrlr supports */
+ u_int32_t mask; /* 14: mask for valid address */
+ u_int32_t bootpri; /* 15: boot priority for autoboot */
+ u_int32_t dostype; /* 16: filesystem type */
+ u_int32_t baud; /* 17: serial handler baud rate */
+ u_int32_t control; /* 18: control word for fs */
+ u_int32_t bootblocks; /* 19: blocks containing boot code */
+ u_int32_t fsize; /* 20: file system block size */
+ u_int32_t frag; /* 21: allowable frags per block */
+ u_int32_t cpg; /* 22: cylinders per group */
+};
+
+struct partblock {
+ u_int32_t id; /* 'PART' */
+ u_int32_t nsumlong; /* number of longs in check sum */
+ u_int32_t chksum; /* simple additive with wrap checksum */
+ u_int32_t hostid; /* scsi target of host */
+ u_int32_t next; /* next in chain */
+ u_int32_t flags; /* see below */
+ u_int32_t resv1[3];
+ u_char partname[32]; /* (BCPL) part name (may not be unique) */
+ u_int32_t resv2[15];
+ struct ados_environ e;
+#if never_use_secsize
+ u_int32_t extra[9]; /* 8 for extra added to environ */
+#endif
+};
+
+#define PBF_BOOTABLE 0x1 /* partition is bootable */
+#define PBF_NOMOUNT 0x2 /* partition should be mounted */
+
+struct badblock {
+ u_int32_t id; /* 'BADB' */
+ u_int32_t nsumlong; /* number of longs in check sum */
+ u_int32_t chksum; /* simple additive with wrap checksum */
+ u_int32_t hostid; /* scsi target of host */
+ u_int32_t next; /* next in chain */
+ u_int32_t resv;
+ struct badblockent {
+ u_int32_t badblock;
+ u_int32_t goodblock;
+ } badtab[0]; /* 61 for secsize == 512 */
+};
+
+struct fsblock {
+ u_int32_t id; /* 'FSHD' */
+ u_int32_t nsumlong; /* number of longs in check sum */
+ u_int32_t chksum; /* simple additive with wrap checksum */
+ u_int32_t hostid; /* scsi target of host */
+ u_int32_t next; /* next in chain */
+ u_int32_t flags;
+ u_int32_t resv1[2];
+ u_int32_t dostype; /* this is a file system for this type */
+ u_int32_t version; /* version of this fs */
+ u_int32_t patchflags; /* describes which functions to replace */
+ u_int32_t type; /* zero */
+ u_int32_t task; /* zero */
+ u_int32_t lock; /* zero */
+ u_int32_t handler; /* zero */
+ u_int32_t stacksize; /* to use when loading handler */
+ u_int32_t priority; /* to run the fs at. */
+ u_int32_t startup; /* zero */
+ u_int32_t lsegblocks; /* linked list of lsegblocks of fs code */
+ u_int32_t globalvec; /* bcpl vector not used mostly */
+#if never_use_secsize
+ u_int32_t resv2[44];
+#endif
+};
+
+struct lsegblock {
+ u_int32_t id; /* 'LSEG' */
+ u_int32_t nsumlong; /* number of longs in check sum */
+ u_int32_t chksum; /* simple additive with wrap checksum */
+ u_int32_t hostid; /* scsi target of host */
+ u_int32_t next; /* next in chain */
+ u_int32_t loaddata[0]; /* load segment data, 123 for secsize == 512 */
+};
+
+#define RDBLOCK_ID 0x5244534b /* 'RDSK' */
+#define PARTBLOCK_ID 0x50415254 /* 'PART' */
+#define BADBLOCK_ID 0x42414442 /* 'BADB' */
+#define FSBLOCK_ID 0x46534844 /* 'FSHD' */
+#define LSEGBLOCK_ID 0x4c534547 /* 'LSEG' */
+
+/*
+ * volume header for "LIF" format volumes
+ */
+struct lifvol {
+ short vol_id;
+ char vol_label[6];
+ u_int vol_addr;
+ short vol_oct;
+ short vol_dummy;
+ u_int vol_dirsize;
+ short vol_version;
+ short vol_zero;
+ u_int vol_number;
+ u_int vol_lastvol;
+ u_int vol_length;
+ char vol_toc[6];
+ char vol_dummy1[198];
+
+ u_int ipl_addr;
+ u_int ipl_size;
+ u_int ipl_entry;
+
+ u_int vol_dummy2;
+};
+
+struct lifdir {
+ char dir_name[10];
+ u_short dir_type;
+ u_int dir_addr;
+ u_int dir_length;
+ char dir_toc[6];
+ short dir_flag;
+ u_int dir_implement;
+};
+
+struct lif_load {
+ int address;
+ int count;
+};
+
+#define HPUX_MAGIC 0x8b7f6a3c
+#define HPUX_MAXPART 16
+struct hpux_label {
+ int32_t hl_magic1;
+ u_int32_t hl_magic;
+ int32_t hl_version;
+ struct {
+ int32_t hlp_blah[2];
+ int32_t hlp_start;
+ int32_t hlp_length;
+ } hl_parts[HPUX_MAXPART];
+ u_int8_t hl_flags[HPUX_MAXPART];
+#define HPUX_PART_ROOT 0x10
+#define HPUX_PART_SWAP 0x14
+#define HPUX_PART_BOOT 0x32
+ int32_t hl_blah[3*16];
+ u_int16_t hl_boot;
+ u_int16_t hl_reserved;
+ int32_t hl_magic2;
+};
+
+#define LIF_VOL_ID -32768
+#define LIF_VOL_OCT 4096
+#define LIF_DIR_SWAP 0x5243
+#define LIF_DIR_HPLBL 0xa271
+#define LIF_DIR_FS 0xcd38
+#define LIF_DIR_IOMAP 0xcd60
+#define LIF_DIR_HPUX 0xcd80
+#define LIF_DIR_ISL 0xce00
+#define LIF_DIR_PAD 0xcffe
+#define LIF_DIR_AUTO 0xcfff
+#define LIF_DIR_EST 0xd001
+#define LIF_DIR_TYPE 0xe942
+
+#define LIF_DIR_FLAG 0x8001 /* dont ask me! */
+#define LIF_SECTSIZE 256
+
+#define LIF_NUMDIR 16
+
+#define LIF_VOLSTART 0
+#define LIF_VOLSIZE sizeof(struct lifvol)
+#define LIF_DIRSTART 2048
+#define LIF_DIRSIZE (LIF_NUMDIR * sizeof(struct lifdir))
+#define LIF_FILESTART 8192
+
+#define btolifs(b) (((b) + (LIF_SECTSIZE - 1)) / LIF_SECTSIZE)
+#define lifstob(s) ((s) * LIF_SECTSIZE)
+#define lifstodb(s) ((s) * LIF_SECTSIZE / DEV_BSIZE)
+
+/* SGI */
+struct devparms {
+ 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;
+} __attribute__((__packed__));
+
+struct sgilabel {
+#define SGILABEL_MAGIC 0xbe5a941
+ u_int32_t magic;
+ int16_t root;
+ int16_t swap;
+ char bootfile[16];
+ struct devparms dp;
+ struct {
+ char name[8];
+ int32_t block;
+ int32_t bytes;
+ } voldir[15];
+ struct {
+ int32_t blocks;
+ int32_t first;
+ int32_t type;
+ } partitions[MAXPARTITIONS];
+ int32_t checksum;
+ int32_t _pad;
+} __attribute__((__packed__));
+
+#define SGI_PTYPE_VOLHDR 0
+#define SGI_PTYPE_RAW 3
+#define SGI_PTYPE_BSD 4
+#define SGI_PTYPE_VOLUME 6
+#define SGI_PTYPE_EFS 7
+#define SGI_PTYPE_LVOL 8
+#define SGI_PTYPE_RLVOL 9
+#define SGI_PTYPE_XFS 10
+#define SGI_PTYPE_XFSLOG 11
+#define SGI_PTYPE_XLV 12
+#define SGI_PTYPE_XVM 13
+
+
#include <sys/dkbad.h>
struct cpu_disklabel {
- struct dos_partition dosparts[NDOSPART];
- struct dkbad bad;
+ enum disklabel_tag labeltag;
+ int labelsector;
+ union {
+ struct {
+ } _alpha;
+ struct {
+ struct dos_partition dosparts[NDOSPART];
+ struct dkbad bad;
+ } _i386;
+ struct {
+ u_int32_t rdblock; /* RDBNULL -> inval. */
+ u_int32_t pblist[MAXPARTITIONS];/* pblock number */
+ int pbindex[MAXPARTITIONS]; /* index of pblock */
+ int valid; /* valid? */
+ } _amiga;
+ struct {
+ struct lifvol lifvol;
+ struct lifdir lifdir[LIF_NUMDIR];
+ struct hpux_label hplabel;
+ } _hppa;
+ } u;
};
-#define DKBAD(x) ((x)->bad)
-
-/* Isolate the relevant bits to get sector and cylinder. */
-#define DPSECT(s) ((s) & 0x3f)
-#define DPCYL(c, s) ((c) + (((s) & 0xc0) << 2))
+#define DKBAD(x) ((x)->u._i386.bad)
-#endif /* !_MIPS_DISKLABEL_H_ */
+#endif /* _MACHINE_DISKLABEL_H_ */
diff --git a/sys/arch/mips64/mips64/disksubr.c b/sys/arch/mips64/mips64/disksubr.c
index 278ac87c471..8ff5c4b0449 100644
--- a/sys/arch/mips64/mips64/disksubr.c
+++ b/sys/arch/mips64/mips64/disksubr.c
@@ -1,7 +1,8 @@
-/* $OpenBSD: disksubr.c,v 1.4 2004/08/11 10:21:08 deraadt Exp $ */
-/* $NetBSD: disksubr.c,v 1.21 1996/05/03 19:42:03 christos Exp $ */
+/* $OpenBSD: disksubr.c,v 1.5 2004/08/23 14:24:56 pefo Exp $ */
/*
+ * Copyright (c) 1999 Michael Shalayeff
+ * Copyright (c) 1997 Niklas Hallqvist
* Copyright (c) 1996 Theo de Raadt
* Copyright (c) 1982, 1986, 1988 Regents of the University of California.
* All rights reserved.
@@ -14,11 +15,7 @@
* 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
+ * 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.
*
@@ -37,6 +34,19 @@
* @(#)ufs_disksubr.c 7.16 (Berkeley) 5/4/91
*/
+/*
+ * This disksubr.c module started to take it's present form on OpenBSD/alpha
+ * but it was always thought it should be made completely MI and not need to
+ * be in that alpha-specific tree at all.
+ *
+ * XXX The DOS partitioning code is not endian-independent, only native
+ * endian DOS partition tables can be parsed yet.
+ *
+ * XXX Amiga RDB partitioning is not understood yet.
+ *
+ * XXX HPUX disklabel is not understood yet.
+ */
+
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/buf.h>
@@ -45,12 +55,45 @@
#include <sys/syslog.h>
#include <sys/disk.h>
-#include <mips64/archtype.h>
+/* The native defaults... */
+#if defined(alpha) && !defined(DISKLABEL_ALPHA)
+#define DISKLABEL_ALPHA
+#elif (defined(i386) || defined(arc)) && !defined(DISKLABEL_I386)
+#define DISKLABEL_I386
+#elif defined(amiga) && !defined(DISKLABEL_AMIGA)
+#define DISKLABEL_AMIGA
+#elif defined(hppa) && !defined(DISKLABEL_HPPA)
+#define DISKLABEL_HPPA
+#elif defined(__sgi__) && !defined(DISKLABEL_SGI)
+#define DISKLABEL_SGI
+#endif
#define b_cylin b_resid
-#define BOOT_MAGIC 0xAA55
-#define BOOT_MAGIC_OFF (DOSPARTOFF+NDOSPART*sizeof(struct dos_partition))
+#if defined(DISKLABEL_I386) || defined(DISKLABEL_ALPHA) || defined(DISKLABEL_AMIGA) || defined(DISKLABEL_HPPA) || defined(DISKLABEL_SGI) || defined(DISKLABEL_ALL)
+void swapdisklabel(struct disklabel *d);
+char *readbsdlabel(struct buf *, void (*)(struct buf *), int, int,
+ int, int, struct disklabel *, int);
+#endif
+#if defined(DISKLABEL_I386) || defined(DISKLABEL_ALL)
+char *readdoslabel(struct buf *, void (*)(struct buf *),
+ struct disklabel *, struct cpu_disklabel *, int *, int *, int);
+#endif
+#if defined(DISKLABEL_AMIGA) || defined(DISKLABEL_ALL)
+char *readamigalabel(struct buf *, void (*)(struct buf *),
+ struct disklabel *, struct cpu_disklabel *, int);
+#endif
+#if defined(DISKLABEL_HPPA) || defined(DISKLABEL_ALL)
+char *readliflabel(struct buf *, void (*)(struct buf *),
+ struct disklabel *, struct cpu_disklabel *, int *, int *, int);
+#endif
+#if defined(DISKLABEL_SGI) || defined(DISKLABEL_ALL)
+char *readsgilabel(struct buf *, void (*)(struct buf *),
+ struct disklabel *, struct cpu_disklabel *, int *, int *, int);
+void map_sgi_label(struct disklabel *, struct sgilabel *);
+#endif
+
+static enum disklabel_tag probe_order[] = { LABELPROBES, -1 };
void
dk_establish(dk, dev)
@@ -59,42 +102,158 @@ dk_establish(dk, dev)
{
}
+#if defined(DISKLABEL_I386) || defined(DISKLABEL_ALPHA) || defined(DISKLABEL_AMIGA) || defined(DISKLABEL_HPPA) || defined(DISKLABEL_SGI) || defined(DISKLABEL_ALL)
+
+/*
+ * Byteswap all the fields that might be swapped.
+ */
+void
+swapdisklabel(dlp)
+ struct disklabel *dlp;
+{
+ int i;
+ struct partition *pp;
+
+ swap32(dlp->d_magic);
+ swap16(dlp->d_type);
+ swap16(dlp->d_subtype);
+ swap32(dlp->d_secsize);
+ swap32(dlp->d_nsectors);
+ swap32(dlp->d_ntracks);
+ swap32(dlp->d_ncylinders);
+ swap32(dlp->d_secpercyl);
+ swap32(dlp->d_secperunit);
+ swap16(dlp->d_sparespertrack);
+ swap16(dlp->d_sparespercyl);
+ swap32(dlp->d_acylinders);
+ swap16(dlp->d_rpm);
+ swap16(dlp->d_interleave);
+ swap16(dlp->d_trackskew);
+ swap16(dlp->d_cylskew);
+ swap32(dlp->d_headswitch);
+ swap32(dlp->d_trkseek);
+ swap32(dlp->d_flags);
+ for (i = 0; i < NDDATA; i++)
+ swap32(dlp->d_drivedata[i]);
+ for (i = 0; i < NSPARE; i++)
+ swap32(dlp->d_spare[i]);
+ swap32(dlp->d_magic2);
+ swap16(dlp->d_checksum);
+ swap16(dlp->d_npartitions);
+ swap32(dlp->d_bbsize);
+ swap32(dlp->d_sbsize);
+ for (i = 0; i < MAXPARTITIONS; i++) {
+ pp = &dlp->d_partitions[i];
+ swap32(pp->p_size);
+ swap32(pp->p_offset);
+ swap32(pp->p_fsize);
+ swap16(pp->p_cpg);
+ }
+}
+
+/*
+ * Try to read a standard BSD disklabel at a certain sector.
+ */
+char *
+readbsdlabel(bp, strat, cyl, sec, off, endian, lp, spoofonly)
+ struct buf *bp;
+ void (*strat)(struct buf *);
+ int cyl, sec, off, endian;
+ struct disklabel *lp;
+ int spoofonly;
+{
+ struct disklabel *dlp;
+ char *msg = NULL;
+ u_int16_t cksum;
+ u_int32_t magic;
+
+ if (endian != LITTLE_ENDIAN && endian != BIG_ENDIAN)
+ panic("readbsdlabel: unsupported byteorder %d", endian);
+
+ /* don't read the on-disk label if we are in spoofed-only mode */
+ if (spoofonly)
+ return (NULL);
+
+ bp->b_blkno = sec;
+ bp->b_cylin = cyl;
+ bp->b_bcount = lp->d_secsize;
+ bp->b_flags = B_BUSY | B_READ;
+ (*strat)(bp);
+
+ /* if successful, locate disk label within block and validate */
+ if (biowait(bp)) {
+ /* XXX we return the faked label built so far */
+ msg = "disk label I/O error";
+ return (msg);
+ }
+
+ magic = endian == BIG_ENDIAN ? htobe32(DISKMAGIC) : htole32(DISKMAGIC);
+
+ /*
+ * If off is negative, search until the end of the sector for
+ * the label, otherwise, just look at the specific location
+ * we're given.
+ */
+ dlp = (struct disklabel *)(bp->b_data + (off >= 0 ? off : 0));
+ do {
+ if (dlp->d_magic != magic || dlp->d_magic2 != magic) {
+ if (msg == NULL)
+ msg = "no disk label";
+ } else {
+ cksum = dkcksum(dlp);
+ if (endian != BYTE_ORDER)
+ swapdisklabel(dlp);
+ if (dlp->d_npartitions > MAXPARTITIONS || cksum != 0) {
+ msg = "disk label corrupted";
+ /* swap back if necessary. */
+ if (off < 0 && endian != BYTE_ORDER)
+ swapdisklabel(dlp);
+ } else {
+ *lp = *dlp;
+ /* Recalc magic on foreign labels */
+ if (endian != BYTE_ORDER) {
+ lp->d_checksum = 0;
+ lp->d_checksum = dkcksum(lp);
+ }
+ msg = NULL;
+ break;
+ }
+ }
+ if (off >= 0)
+ break;
+ dlp = (struct disklabel *)((char *)dlp + sizeof(int32_t));
+ } while (dlp <= (struct disklabel *)(bp->b_data + lp->d_secsize -
+ sizeof(*dlp)));
+ return (msg);
+}
+#endif
+
/*
* Attempt to read a disk label from a device
- * using the indicated stategy routine.
+ * using the indicated strategy routine.
* The label must be partly set up before this:
* secpercyl, secsize and anything required for a block i/o read
* operation in the driver's strategy/start routines
* must be filled in before calling us.
*
- * If dos partition table requested, attempt to load it and
- * find disklabel inside a DOS partition. Also, if bad block
- * table needed, attempt to extract it as well. Return buffer
- * for use in signalling errors if requested.
- *
- * We would like to check if each MBR has a valid BOOT_MAGIC, but
- * we cannot because it doesn't always exist. So.. we assume the
- * MBR is valid.
- *
* Returns null on success and an error string on failure.
*/
char *
readdisklabel(dev, strat, lp, osdep, spoofonly)
dev_t dev;
- void (*strat) __P((struct buf *));
+ void (*strat)(struct buf *);
struct disklabel *lp;
struct cpu_disklabel *osdep;
int spoofonly;
{
- struct dos_partition *dp = osdep->dosparts, *dp2;
- struct dkbad *bdp = &DKBAD(osdep);
- struct buf *bp;
- struct disklabel *dlp;
- char *msg = NULL, *cp;
- int dospartoff, cyl, i, ourpart = -1;
+ struct buf *bp = NULL;
+ char *msg = "no disk label";
+ enum disklabel_tag *tp;
+ int i;
+ struct disklabel minilabel, fallbacklabel;
/* minimal requirements for archtypal disk label */
- if (lp->d_secsize == 0)
+ if (lp->d_secsize < DEV_BSIZE)
lp->d_secsize = DEV_BSIZE;
if (lp->d_secperunit == 0)
lp->d_secperunit = 0x1fffffff;
@@ -110,14 +269,120 @@ readdisklabel(dev, strat, lp, osdep, spoofonly)
if (lp->d_partitions[i].p_size == 0)
lp->d_partitions[i].p_size = 0x1fffffff;
lp->d_partitions[i].p_offset = 0;
+ minilabel = fallbacklabel = *lp;
/* get a buffer and initialize it */
bp = geteblk((int)lp->d_secsize);
bp->b_dev = dev;
+ for (tp = probe_order; msg && *tp != -1; tp++) {
+ switch (*tp) {
+ case DLT_ALPHA:
+#if defined(DISKLABEL_ALPHA) || defined(DISKLABEL_ALL)
+ msg = readbsdlabel(bp, strat, 0, ALPHA_LABELSECTOR,
+ ALPHA_LABELOFFSET, LITTLE_ENDIAN, lp, spoofonly);
+#endif
+ break;
+
+ case DLT_I386:
+#if defined(DISKLABEL_I386) || defined(DISKLABEL_ALL)
+ msg = readdoslabel(bp, strat, lp, osdep, 0, 0, spoofonly);
+ if (msg)
+ /* Fallback alternative */
+ fallbacklabel = *lp;
+#endif
+ break;
+
+ case DLT_AMIGA:
+#if defined(DISKLABEL_AMIGA) || defined(DISKLABEL_ALL)
+ msg = readamigalabel(bp, strat, lp, osdep, spoofonly);
+#endif
+ break;
+
+ case DLT_HPPA:
+#if defined(DISKLABEL_HPPA) || defined(DISKLABEL_ALL)
+ msg = readliflabel(bp, strat, lp, osdep, 0, 0, spoofonly);
+#endif
+ break;
+
+ case DLT_SGI:
+#if defined(DISKLABEL_SGI) || defined(DISKLABEL_ALL)
+ msg = readsgilabel(bp, strat, lp, osdep, 0, 0, spoofonly);
+ if (msg)
+ /* Fallback alternative */
+ fallbacklabel = *lp;
+#endif
+ break;
+
+ default:
+ panic("unrecognized disklabel tag %d", *tp);
+ }
+ if (msg)
+ *lp = minilabel;
+ }
+
+ /* Record metainformation about the disklabel. */
+ if (msg == NULL) {
+ osdep->labelsector = bp->b_blkno;
+ osdep->labeltag = *tp;
+ }
+
+#if defined(CD9660)
+ if (msg && iso_disklabelspoof(dev, strat, lp) == 0)
+ msg = NULL;
+#endif
+
+ /* If there was an error, still provide a decent fake one. */
+ if (msg)
+ *lp = fallbacklabel;
+
+done:
+ if (bp) {
+ bp->b_flags |= B_INVAL;
+ brelse(bp);
+ }
+ return (msg);
+}
+
+#if defined(DISKLABEL_I386) || defined(DISKLABEL_ALL)
+/*
+ * If dos partition table requested, attempt to load it and
+ * find disklabel inside a DOS partition. Also, if bad block
+ * table needed, attempt to extract it as well. Return buffer
+ * for use in signalling errors if requested.
+ *
+ * We would like to check if each MBR has a valid BOOT_MAGIC, but
+ * we cannot because it doesn't always exist. So.. we assume the
+ * MBR is valid.
+ */
+char *
+readdoslabel(bp, strat, lp, osdep, partoffp, cylp, spoofonly)
+ struct buf *bp;
+ void (*strat)(struct buf *);
+ struct disklabel *lp;
+ struct cpu_disklabel *osdep;
+ int *partoffp;
+ int *cylp;
+ int spoofonly;
+{
+ struct dos_partition *dp = osdep->u._i386.dosparts, *dp2;
+ struct dkbad *db, *bdp = &DKBAD(osdep);
+ char *msg = NULL, *cp;
+ int dospartoff, cyl, i, ourpart = -1;
+ dev_t dev;
+
+ if (lp->d_secpercyl == 0) {
+ msg = "invalid label, d_secpercyl == 0";
+ return (msg);
+ }
+ if (lp->d_secsize == 0) {
+ msg = "invalid label, d_secsize == 0";
+ return (msg);
+ }
+
/* do dos partitions in the process of getting disklabel? */
dospartoff = 0;
- cyl = LABELSECTOR / lp->d_secpercyl;
+ cyl = I386_LABELSECTOR / lp->d_secpercyl;
if (dp) {
daddr_t part_blkno = DOSBBSECTOR;
unsigned long extoff = 0;
@@ -130,6 +395,8 @@ readdisklabel(dev, strat, lp, osdep, spoofonly)
while (wander && n < 8 && loop < 8) {
loop++;
wander = 0;
+ if (part_blkno < extoff)
+ part_blkno = extoff;
/* read boot record */
bp->b_blkno = part_blkno;
@@ -141,45 +408,45 @@ readdisklabel(dev, strat, lp, osdep, spoofonly)
/* if successful, wander through dos partition table */
if (biowait(bp)) {
msg = "dos partition I/O error";
- goto done;
+ if (partoffp)
+ *partoffp = -1;
+ return (msg);
}
- if (((int *)bp->b_data)[0] == 0x01084025 &&
- ((int *)bp->b_data)[1] == 0x01294825) {
- goto nodoslabel;
- }
- bcopy(bp->b_data + DOSPARTOFF, dp, NDOSPART * sizeof(*dp));
+ bcopy(bp->b_data + DOSPARTOFF, dp,
+ NDOSPART * sizeof(*dp));
if (ourpart == -1) {
/* Search for our MBR partition */
- for (dp2=dp, i=0; i < NDOSPART && ourpart == -1;
- i++, dp2++)
- if (get_le(&dp2->dp_size) &&
+ for (dp2=dp, i=0;
+ i < NDOSPART && ourpart == -1; i++, dp2++)
+ if (dp2->dp_size &&
dp2->dp_typ == DOSPTYP_OPENBSD)
ourpart = i;
- for (dp2=dp, i=0; i < NDOSPART && ourpart == -1;
- i++, dp2++)
- if (get_le(&dp2->dp_size) &&
+ for (dp2=dp, i=0;
+ i < NDOSPART && ourpart == -1; i++, dp2++)
+ if (dp2->dp_size &&
dp2->dp_typ == DOSPTYP_FREEBSD)
ourpart = i;
- for (dp2=dp, i=0; i < NDOSPART && ourpart == -1;
- i++, dp2++)
- if (get_le(&dp2->dp_size) &&
+ for (dp2=dp, i=0;
+ i < NDOSPART && ourpart == -1; i++, dp2++)
+ if (dp2->dp_size &&
dp2->dp_typ == DOSPTYP_NETBSD)
ourpart = i;
if (ourpart == -1)
goto donot;
/*
- * This is our MBR partition. need sector address
- * for SCSI/IDE, cylinder for ESDI/ST506/RLL
+ * This is our MBR partition. need sector
+ * address for SCSI/IDE, cylinder for
+ * ESDI/ST506/RLL
*/
dp2 = &dp[ourpart];
- dospartoff = get_le(&dp2->dp_start) + part_blkno;
+ dospartoff = dp2->dp_start + part_blkno;
cyl = DPCYL(dp2->dp_scyl, dp2->dp_ssect);
/* XXX build a temporary disklabel */
- lp->d_partitions[0].p_size = get_le(&dp2->dp_size);
- lp->d_partitions[0].p_offset =
- get_le(&dp2->dp_start) + part_blkno;
+ lp->d_partitions[0].p_size = dp2->dp_size;
+ lp->d_partitions[0].p_offset = dp2->dp_start +
+ part_blkno;
if (lp->d_ntracks == 0)
lp->d_ntracks = dp2->dp_ehd + 1;
if (lp->d_nsectors == 0)
@@ -198,13 +465,11 @@ donot:
if (dp2->dp_typ == DOSPTYP_OPENBSD)
continue;
- if (get_le(&dp2->dp_size) > lp->d_secperunit)
- continue;
- if (get_le(&dp2->dp_size))
- pp->p_size = get_le(&dp2->dp_size);
- if (get_le(&dp2->dp_start))
+ if (dp2->dp_size)
+ pp->p_size = dp2->dp_size;
+ if (dp2->dp_start)
pp->p_offset =
- get_le(&dp2->dp_start) + part_blkno;
+ dp2->dp_start + part_blkno;
switch (dp2->dp_typ) {
case DOSPTYP_UNUSED:
@@ -238,9 +503,11 @@ donot:
n++;
break;
case DOSPTYP_EXTEND:
- part_blkno = get_le(&dp2->dp_start) + extoff;
- if (!extoff)
- extoff = get_le(&dp2->dp_start);
+ part_blkno = dp2->dp_start + extoff;
+ if (!extoff) {
+ extoff = dp2->dp_start;
+ part_blkno = 0;
+ }
wander = 1;
break;
default:
@@ -252,54 +519,30 @@ donot:
}
lp->d_bbsize = 8192;
lp->d_sbsize = 64*1024; /* XXX ? */
- lp->d_npartitions = MAXPARTITIONS;
+ lp->d_npartitions = n > 0 ? n + 8 : 3;
}
-nodoslabel:
- /* don't read the on-disk label if we are in spoofed-only mode */
- if (spoofonly)
- goto done;
+ /* record the OpenBSD partition's placement for the caller */
+ if (partoffp)
+ *partoffp = dospartoff;
+ if (cylp)
+ *cylp = cyl;
/* next, dig out disk label */
- bp->b_blkno = dospartoff + LABELSECTOR;
- bp->b_cylin = cyl;
- bp->b_bcount = lp->d_secsize;
- bp->b_flags = B_BUSY | B_READ;
- (*strat)(bp);
-
- /* if successful, locate disk label within block and validate */
- if (biowait(bp)) {
- /* XXX we return the faked label built so far */
- msg = "disk label I/O error";
- goto done;
- }
- for (dlp = (struct disklabel *)bp->b_data;
- dlp <= (struct disklabel *)(bp->b_data + lp->d_secsize - sizeof(*dlp));
- dlp = (struct disklabel *)((char *)dlp + sizeof(long))) {
- if (dlp->d_magic != DISKMAGIC || dlp->d_magic2 != DISKMAGIC) {
- if (msg == NULL)
- msg = "no disk label";
- } else if (dlp->d_npartitions > MAXPARTITIONS ||
- dkcksum(dlp) != 0)
- msg = "disk label corrupted";
- else {
- *lp = *dlp;
- msg = NULL;
- break;
- }
- }
-
- if (msg) {
-#if defined(CD9660)
- if (iso_disklabelspoof(dev, strat, lp) == 0)
- msg = NULL;
-#endif
- goto done;
- }
+ msg = readbsdlabel(bp, strat, cyl, dospartoff + I386_LABELSECTOR, -1,
+ LITTLE_ENDIAN, lp, spoofonly);
+ if (msg)
+ return (msg);
/* obtain bad sector table if requested and present */
if (bdp && (lp->d_flags & D_BADSECT)) {
- struct dkbad *db;
+ /*
+ * get a new buffer and initialize it as callers trust the
+ * buffer given to us, to point at the disklabel sector.
+ */
+ dev = bp->b_dev;
+ bp = geteblk((int)lp->d_secsize);
+ bp->b_dev = dev;
i = 0;
do {
@@ -315,13 +558,13 @@ nodoslabel:
(*strat)(bp);
/* if successful, validate, otherwise try another */
- if (biowait(bp)) {
+ if (biowait(bp))
msg = "bad sector table I/O error";
- } else {
+ else {
db = (struct dkbad *)(bp->b_data);
#define DKBAD_MAGIC 0x4321
- if (db->bt_mbz == 0
- && db->bt_flag == DKBAD_MAGIC) {
+ if (db->bt_mbz == 0 &&
+ db->bt_flag == DKBAD_MAGIC) {
msg = NULL;
*bdp = *db;
break;
@@ -329,14 +572,305 @@ nodoslabel:
msg = "bad sector table corrupted";
}
} while ((bp->b_flags & B_ERROR) && (i += 2) < 10 &&
- i < lp->d_nsectors);
+ i < lp->d_nsectors);
+
+ /* Give back the bad block buffer. */
+ bp->b_flags |= B_INVAL;
+ brelse(bp);
}
+ return (msg);
+}
+#endif
-done:
- bp->b_flags |= B_INVAL;
- brelse(bp);
+#if defined(DISKLABEL_AMIGA) || defined(DISKLABEL_ALL)
+/*
+ * XXX RDB parsing is missing still.
+ */
+char *
+readamigalabel(bp, strat, lp, osdep, spoofonly)
+ struct buf *bp;
+ void (*strat)(struct buf *);
+ struct disklabel *lp;
+ struct cpu_disklabel *osdep;
+ int spoofonly;
+{
+ char *msg;
+
+ msg = readbsdlabel(bp, strat, 0, AMIGA_LABELSECTOR, AMIGA_LABELOFFSET,
+ BIG_ENDIAN, lp, spoofonly);
return (msg);
}
+#endif
+
+#if defined(DISKLABEL_HPPA) || defined(DISKLABEL_ALL)
+char *
+readliflabel (bp, strat, lp, osdep, partoffp, cylp, spoofonly)
+ struct buf *bp;
+ void (*strat)(struct buf *);
+ struct disklabel *lp;
+ struct cpu_disklabel *osdep;
+ int *partoffp;
+ int *cylp;
+ int spoofonly;
+{
+ int fsoff;
+
+ /* read LIF volume header */
+ bp->b_blkno = btodb(LIF_VOLSTART);
+ bp->b_bcount = lp->d_secsize;
+ bp->b_flags = B_BUSY | B_READ;
+ bp->b_cylin = btodb(LIF_VOLSTART) / lp->d_secpercyl;
+ (*strat)(bp);
+
+ if (biowait(bp)) {
+ if (partoffp)
+ *partoffp = -1;
+ return "LIF volume header I/O error";
+ }
+
+ bcopy (bp->b_data, &osdep->u._hppa.lifvol, sizeof(struct lifvol));
+ if (osdep->u._hppa.lifvol.vol_id != LIF_VOL_ID) {
+ fsoff = 0;
+ } else {
+ struct lifdir *p;
+ struct buf *dbp;
+ dev_t dev;
+
+ dev = bp->b_dev;
+ dbp = geteblk(LIF_DIRSIZE);
+ dbp->b_dev = dev;
+
+ /* read LIF directory */
+ dbp->b_blkno = lifstodb(osdep->u._hppa.lifvol.vol_addr);
+ dbp->b_bcount = lp->d_secsize;
+ dbp->b_flags = B_BUSY | B_READ;
+ dbp->b_cylin = dbp->b_blkno / lp->d_secpercyl;
+ (*strat)(dbp);
+
+ if (biowait(dbp)) {
+ if (partoffp)
+ *partoffp = -1;
+
+ dbp->b_flags |= B_INVAL;
+ brelse(dbp);
+ return ("LIF directory I/O error");
+ }
+
+ bcopy(dbp->b_data, osdep->u._hppa.lifdir, LIF_DIRSIZE);
+ dbp->b_flags |= B_INVAL;
+ brelse(dbp);
+
+ /* scan for LIF_DIR_FS dir entry */
+ for (fsoff = -1, p = &osdep->u._hppa.lifdir[0];
+ fsoff < 0 && p < &osdep->u._hppa.lifdir[LIF_NUMDIR]; p++) {
+ if (p->dir_type == LIF_DIR_FS ||
+ p->dir_type == LIF_DIR_HPLBL)
+ break;
+ }
+
+ if (p->dir_type == LIF_DIR_FS)
+ fsoff = lifstodb(p->dir_addr);
+ else if (p->dir_type == LIF_DIR_HPLBL) {
+ struct hpux_label *hl;
+ struct partition *pp;
+ u_int8_t fstype;
+ int i;
+
+ dev = bp->b_dev;
+ dbp = geteblk(LIF_DIRSIZE);
+ dbp->b_dev = dev;
+
+ /* read LIF directory */
+ dbp->b_blkno = lifstodb(p->dir_addr);
+ dbp->b_bcount = lp->d_secsize;
+ dbp->b_flags = B_BUSY | B_READ;
+ dbp->b_cylin = dbp->b_blkno / lp->d_secpercyl;
+ (*strat)(dbp);
+
+ if (biowait(dbp)) {
+ if (partoffp)
+ *partoffp = -1;
+
+ dbp->b_flags |= B_INVAL;
+ brelse(dbp);
+ return ("HOUX label I/O error");
+ }
+
+ bcopy(dbp->b_data, &osdep->u._hppa.hplabel,
+ sizeof(osdep->u._hppa.hplabel));
+ dbp->b_flags |= B_INVAL;
+ brelse(dbp);
+
+ hl = &osdep->u._hppa.hplabel;
+ if (hl->hl_magic1 != hl->hl_magic2 ||
+ hl->hl_magic != HPUX_MAGIC ||
+ hl->hl_version != 1) {
+ if (partoffp)
+ *partoffp = -1;
+
+ return "HPUX label magic mismatch";
+ }
+
+ lp->d_bbsize = 8192;
+ lp->d_sbsize = 8192;
+ for (i = 0; i < MAXPARTITIONS; i++) {
+ lp->d_partitions[i].p_size = 0;
+ lp->d_partitions[i].p_offset = 0;
+ lp->d_partitions[i].p_fstype = 0;
+ }
+
+ for (i = 0; i < HPUX_MAXPART; i++) {
+ if (!hl->hl_flags[i])
+ continue;
+
+ if (hl->hl_flags[i] == HPUX_PART_ROOT) {
+ pp = &lp->d_partitions[0];
+ fstype = FS_BSDFFS;
+ } else if (hl->hl_flags[i] == HPUX_PART_SWAP) {
+ pp = &lp->d_partitions[1];
+ fstype = FS_SWAP;
+ } else if (hl->hl_flags[i] == HPUX_PART_BOOT) {
+ pp = &lp->d_partitions[RAW_PART + 1];
+ fstype = FS_BSDFFS;
+ } else
+ continue;
+
+ pp->p_size = hl->hl_parts[i].hlp_length * 2;
+ pp->p_offset = hl->hl_parts[i].hlp_start * 2;
+ pp->p_fstype = fstype;
+ }
+
+ lp->d_partitions[RAW_PART].p_size = lp->d_secperunit;
+ lp->d_partitions[RAW_PART].p_offset = 0;
+ lp->d_partitions[RAW_PART].p_fstype = FS_UNUSED;
+ lp->d_npartitions = MAXPARTITIONS;
+ lp->d_magic = DISKMAGIC;
+ lp->d_magic2 = DISKMAGIC;
+ lp->d_checksum = 0;
+ lp->d_checksum = dkcksum(lp);
+
+ return (NULL);
+ }
+
+ /* if no suitable lifdir entry found assume zero */
+ if (fsoff < 0) {
+ fsoff = 0;
+ }
+ }
+
+ if (partoffp)
+ *partoffp = fsoff;
+
+ return readbsdlabel(bp, strat, 0, fsoff + HPPA_LABELSECTOR,
+ HPPA_LABELOFFSET, BIG_ENDIAN, lp, spoofonly);
+}
+#endif
+
+#if defined(DISKLABEL_SGI) || defined(DISKLABEL_ALL)
+/*
+ *
+ */
+char *
+readsgilabel(bp, strat, lp, osdep, partoffp, cylp, spoofonly)
+ struct buf *bp;
+ void (*strat)(struct buf *);
+ struct disklabel *lp;
+ struct cpu_disklabel *osdep;
+ int *partoffp;
+ int *cylp;
+ int spoofonly;
+{
+ struct sgilabel *dlp;
+ char *msg = NULL;
+ int fsoffs = 0;
+
+ /* don't read the on-disk label if we are in spoofed-only mode */
+ if (spoofonly)
+ return (NULL);
+
+ if (partoffp)
+ *partoffp = -1;
+
+ bp->b_blkno = 0;
+ bp->b_cylin = 0;
+ bp->b_bcount = lp->d_secsize;
+ bp->b_flags = B_BUSY | B_READ;
+ (*strat)(bp);
+
+ /* if successful, locate disk label within block and validate */
+ if (biowait(bp)) {
+ if (partoffp)
+ *partoffp = -1;
+ return "disk label I/O error";
+ }
+
+ dlp = (struct sgilabel *)(bp->b_data);
+ if (dlp->magic != htobe32(SGILABEL_MAGIC)) {
+ fsoffs = 0;
+ } else {
+ int i, *p, cs;
+
+ cs = 0;
+ p = (int *)dlp;
+ i = sizeof(struct sgilabel) / sizeof(int);
+ while(i--)
+ cs += *p++;
+ if (cs != 0)
+ return "sgilabel checksum error";
+
+ /* Set up partitions i-l if there is no BSD label. */
+ lp->d_secsize = dlp->dp.dp_secbytes;
+ lp->d_nsectors = dlp->dp.dp_secs;
+ lp->d_ntracks = dlp->dp.dp_trks0;
+ lp->d_ncylinders = dlp->dp.dp_cyls;
+ lp->d_interleave = dlp->dp.dp_interleave;
+ lp->d_npartitions = MAXPARTITIONS;
+
+ map_sgi_label(lp, dlp);
+
+ fsoffs = dlp->partitions[0].first;
+ if (dlp->partitions[0].blocks == 0)
+ msg = "no BSD partition";
+ }
+
+ if (msg)
+ return msg;
+
+ if (partoffp)
+ *partoffp = fsoffs;
+
+ msg = readbsdlabel(bp, strat, 0, fsoffs + SGI_LABELSECTOR,
+ SGI_LABELOFFSET, BIG_ENDIAN, lp, spoofonly);
+ return msg;
+}
+
+void
+map_sgi_label(struct disklabel *lp, struct sgilabel *dlp)
+{
+static struct {int m; int b;} maptab[] = {
+ { 0, FS_BSDFFS}, { 1, FS_SWAP}, { 10, FS_BSDFFS},
+ { 3, FS_BSDFFS}, { 4, FS_BSDFFS}, { 5, FS_BSDFFS},
+ { 6, FS_BSDFFS}, { 7, FS_BSDFFS}, { 8, FS_OTHER},
+ { 9, FS_BSDFFS}, { 2, FS_UNUSED}, { 11, FS_BSDFFS},
+ { 12, FS_BSDFFS}, { 13, FS_BSDFFS}, { 14, FS_BSDFFS},
+ { 15, FS_BSDFFS}
+};
+ int i;
+
+ for (i = 0; i < 16; i++) {
+ int bsd = maptab[i].m;
+
+ lp->d_partitions[bsd].p_offset = dlp->partitions[i].first;
+ lp->d_partitions[bsd].p_size = dlp->partitions[i].blocks;
+ lp->d_partitions[bsd].p_fstype = maptab[i].b;
+ if (lp->d_partitions[bsd].p_fstype == FS_BSDFFS) {
+ lp->d_partitions[bsd].p_fsize = 1024;
+ lp->d_partitions[bsd].p_frag = 8;
+ lp->d_partitions[bsd].p_cpg = 16;
+ }
+ }
+}
+#endif
/*
* Check new disk label for sensibility
@@ -356,7 +890,14 @@ setdisklabel(olp, nlp, openmask, osdep)
(nlp->d_secsize % DEV_BSIZE) != 0)
return(EINVAL);
- /* special case to allow disklabel to be invalidated */
+ /*
+ * XXX Nice thought, but it doesn't work, if the intention was to
+ * force a reread at the next *readdisklabel call. That does not
+ * happen. There's still some use for it though as you can pseudo-
+ * partitition the disk.
+ *
+ * Special case to allow disklabel to be invalidated.
+ */
if (nlp->d_magic == 0xffffffff) {
*olp = *nlp;
return (0);
@@ -369,13 +910,14 @@ setdisklabel(olp, nlp, openmask, osdep)
/* XXX missing check if other dos partitions will be overwritten */
while (openmask != 0) {
- i = ffs(openmask) - 1;
+ i = ffs((long)openmask) - 1;
openmask &= ~(1 << i);
if (nlp->d_npartitions <= i)
return (EBUSY);
opp = &olp->d_partitions[i];
npp = &nlp->d_partitions[i];
- if (npp->p_offset != opp->p_offset || npp->p_size < opp->p_size)
+ if (npp->p_offset != opp->p_offset ||
+ npp->p_size < opp->p_size)
return (EBUSY);
/*
* Copy internally-set partition information
@@ -397,101 +939,118 @@ setdisklabel(olp, nlp, openmask, osdep)
/*
* Write disk label back to device after modification.
- * XXX cannot handle OpenBSD partitions in extended partitions!
*/
int
writedisklabel(dev, strat, lp, osdep)
dev_t dev;
- void (*strat) __P((struct buf *));
+ void (*strat)(struct buf *);
struct disklabel *lp;
struct cpu_disklabel *osdep;
{
- struct dos_partition *dp = osdep->dosparts, *dp2;
+ enum disklabel_tag *tp;
+ char *msg = "no disk label";
struct buf *bp;
- struct disklabel *dlp;
- int error, dospartoff, cyl, i;
- int ourpart = -1;
+ struct disklabel dl;
+#if defined(DISKLABEL_I386) || defined(DISKLABEL_HPPA) || defined(DISKLABEL_SGI) || defined(DISKLABEL_ALL)
+ struct cpu_disklabel cdl;
+#endif
+ int labeloffset, error, i, endian, partoff = 0, cyl = 0;
+ u_int64_t csum, *p;
/* get a buffer and initialize it */
bp = geteblk((int)lp->d_secsize);
bp->b_dev = dev;
- /* do dos partitions in the process of getting disklabel? */
- dospartoff = 0;
- cyl = LABELSECTOR / lp->d_secpercyl;
- if (dp) {
- /* read master boot record */
- bp->b_blkno = DOSBBSECTOR;
- bp->b_bcount = lp->d_secsize;
- bp->b_flags = B_BUSY | B_READ;
- bp->b_cylin = DOSBBSECTOR / lp->d_secpercyl;
- (*strat)(bp);
+ /*
+ * I once played with the thought of using osdep->label{tag,sector}
+ * as a cache for knowing where (and what) to write. However, now I
+ * think it might be useful to reprobe if someone has written
+ * a newer disklabel of another type with disklabel(8) and -r.
+ */
+ for (tp = probe_order; msg && *tp != -1; tp++) {
+ dl = *lp;
+ switch (*tp) {
+ case DLT_ALPHA:
+#if defined(DISKLABEL_ALPHA) || defined(DISKLABEL_ALL)
+ msg = readbsdlabel(bp, strat, 0, ALPHA_LABELSECTOR,
+ ALPHA_LABELOFFSET, LITTLE_ENDIAN, &dl, 0);
+ labeloffset = ALPHA_LABELOFFSET;
+ endian = LITTLE_ENDIAN;
+#endif
+ break;
- if ((error = biowait(bp)) != 0)
- goto done;
+ case DLT_I386:
+#if defined(DISKLABEL_I386) || defined(DISKLABEL_ALL)
+ msg = readdoslabel(bp, strat, &dl, &cdl, &partoff,
+ &cyl, 0);
+ labeloffset = I386_LABELOFFSET;
+ endian = LITTLE_ENDIAN;
+#endif
+ break;
- if (((int *)bp->b_data)[0] == 0x01084025 &&
- ((int *)bp->b_data)[1] == 0x01294825) {
- goto nodoslabel;
- }
- /* XXX how do we check veracity/bounds of this? */
- bcopy(bp->b_data + DOSPARTOFF, dp,
- NDOSPART * sizeof(*dp));
-
- for (dp2=dp, i=0; i < NDOSPART && ourpart == -1; i++, dp2++)
- if (get_le(&dp2->dp_size) && dp2->dp_typ == DOSPTYP_OPENBSD)
- ourpart = i;
- for (dp2=dp, i=0; i < NDOSPART && ourpart == -1; i++, dp2++)
- if (get_le(&dp2->dp_size) && dp2->dp_typ == DOSPTYP_FREEBSD)
- ourpart = i;
- for (dp2=dp, i=0; i < NDOSPART && ourpart == -1; i++, dp2++)
- if (get_le(&dp2->dp_size) && dp2->dp_typ == DOSPTYP_NETBSD)
- ourpart = i;
-
- if (ourpart != -1) {
- dp2 = &dp[ourpart];
+ case DLT_AMIGA:
+#if defined(DISKLABEL_AMIGA) || defined(DISKLABEL_ALL)
+ msg = readamigalabel(bp, strat, &dl, &cdl, 0);
+ labeloffset = AMIGA_LABELOFFSET;
+ endian = BIG_ENDIAN;
+#endif
+ break;
- /*
- * need sector address for SCSI/IDE,
- * cylinder for ESDI/ST506/RLL
- */
- dospartoff = get_le(&dp2->dp_start);
- cyl = DPCYL(dp2->dp_scyl, dp2->dp_ssect);
+ case DLT_HPPA:
+#if defined(DISKLABEL_HPPA) || defined(DISKLABEL_ALL)
+ msg = readliflabel(bp, strat, &dl, &cdl, &partoff,
+ &cyl, 0);
+ labeloffset = HPPA_LABELOFFSET;
+ endian = BIG_ENDIAN;
+#endif
+ break;
+
+ case DLT_SGI:
+#if defined(DISKLABEL_SGI) || defined(DISKLABEL_ALL)
+ msg = readsgilabel(bp, strat, &dl, &cdl, &partoff,
+ &cyl, 0);
+ labeloffset = SGI_LABELOFFSET;
+ endian = BIG_ENDIAN;
+#endif
+ break;
+
+ default:
+ panic("unrecognized disklabel tag %d", *tp);
}
}
-nodoslabel:
- /* next, dig out disk label */
- bp->b_blkno = dospartoff + LABELSECTOR;
- bp->b_cylin = cyl;
- bp->b_bcount = lp->d_secsize;
- bp->b_flags = B_BUSY | B_READ;
- (*strat)(bp);
+ if (msg) {
+ if (partoff == -1)
+ return EIO;
- /* if successful, locate disk label within block and validate */
- if ((error = biowait(bp)) != 0)
- goto done;
- for (dlp = (struct disklabel *)bp->b_data;
- dlp <= (struct disklabel *)(bp->b_data + lp->d_secsize - sizeof(*dlp));
- dlp = (struct disklabel *)((char *)dlp + sizeof(long))) {
- if (dlp->d_magic == DISKMAGIC && dlp->d_magic2 == DISKMAGIC &&
- dkcksum(dlp) == 0) {
- *dlp = *lp;
- bp->b_flags = B_BUSY | B_WRITE;
- (*strat)(bp);
- error = biowait(bp);
- goto done;
- }
+ /* Write it in the regular place with native byte order. */
+ labeloffset = LABELOFFSET;
+ endian = BYTE_ORDER;
+ bp->b_blkno = partoff + LABELSECTOR;
+ bp->b_cylin = cyl;
+ bp->b_bcount = lp->d_secsize;
+ }
+
+ if (endian != BYTE_ORDER) {
+ swapdisklabel(lp);
+ /* recalc checksum */
+ lp->d_checksum = 0;
+ lp->d_checksum = dkcksum(lp);
+ }
+
+ *(struct disklabel *)(bp->b_data + labeloffset) = *lp;
+
+ /* Alpha bootblocks are checksummed. */
+ if (*tp == DLT_ALPHA) {
+ for (csum = i = 0, p = (u_int64_t *)bp->b_data; i < 63; i++)
+ csum += *p++;
+ *p = csum;
}
- /* Write it in the regular place. */
- *(struct disklabel *)bp->b_data = *lp;
bp->b_flags = B_BUSY | B_WRITE;
(*strat)(bp);
error = biowait(bp);
- goto done;
-done:
bp->b_flags |= B_INVAL;
brelse(bp);
return (error);
@@ -511,10 +1070,17 @@ bounds_check_with_label(bp, lp, osdep, wlabel)
{
#define blockpersec(count, lp) ((count) * (((lp)->d_secsize) / DEV_BSIZE))
struct partition *p = lp->d_partitions + DISKPART(bp->b_dev);
- int labelsector = blockpersec(lp->d_partitions[RAW_PART].p_offset, lp) +
- LABELSECTOR;
+ int labelsector = blockpersec(lp->d_partitions[RAW_PART].p_offset,
+ lp) + osdep->labelsector;
int sz = howmany(bp->b_bcount, DEV_BSIZE);
+ /* avoid division by zero */
+ if (lp->d_secpercyl == 0) {
+ bp->b_error = EINVAL;
+ goto bad;
+ }
+
+ /* beyond partition? */
if (bp->b_blkno + sz > blockpersec(p->p_size, lp)) {
sz = blockpersec(p->p_size, lp) - bp->b_blkno;
if (sz == 0) {
@@ -533,9 +1099,7 @@ bounds_check_with_label(bp, lp, osdep, wlabel)
/* Overwriting disk label? */
if (bp->b_blkno + blockpersec(p->p_offset, lp) <= labelsector &&
-#if LABELSECTOR != 0
bp->b_blkno + blockpersec(p->p_offset, lp) + sz > labelsector &&
-#endif
(bp->b_flags & B_READ) == 0 && !wlabel) {
bp->b_error = EROFS;
goto bad;