make it possible to handle/mount FDISK-partitioned disk.

extended FDISK partitions are not supported yet.
openbsd code was used as reference.
This commit is contained in:
itojun 2002-06-17 15:07:06 +00:00
parent 1d64dfa199
commit 9e1c373ba9
2 changed files with 77 additions and 36 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: disksubr.c,v 1.20 2002/03/27 20:23:11 wrstuden Exp $ */
/* $NetBSD: disksubr.c,v 1.21 2002/06/17 15:07:06 itojun Exp $ */
/*
* Copyright (c) 1982, 1986, 1988 Regents of the University of California.
@ -127,11 +127,6 @@
#define HFS_PART 4
#define SCRATCH_PART 5
int fat_types[] = { MBR_PTYPE_FAT12, MBR_PTYPE_FAT16S,
MBR_PTYPE_FAT16B, MBR_PTYPE_FAT32,
MBR_PTYPE_FAT32L, MBR_PTYPE_FAT16L,
-1 };
static int getFreeLabelEntry __P((struct disklabel *));
static int whichType __P((struct part_map_entry *, u_int8_t *, int *));
static void setpartition __P((struct part_map_entry *,
@ -142,8 +137,8 @@ static char *read_mac_label __P((dev_t, void (*)(struct buf *),
struct disklabel *, struct cpu_disklabel *));
static char *read_dos_label __P((dev_t, void (*)(struct buf *),
struct disklabel *, struct cpu_disklabel *));
static int get_netbsd_label __P((dev_t dev, void (*strat)(struct buf *),
struct disklabel *lp, daddr_t bno));
static int get_netbsd_label __P((dev_t, void (*)(struct buf *),
struct disklabel *, daddr_t, int));
/*
* Find an entry in the disk label that is unused and return it
@ -409,10 +404,11 @@ read_dos_label(dev, strat, lp, osdep)
struct cpu_disklabel *osdep;
{
struct mbr_partition *dp;
struct partition *pp;
struct buf *bp;
char *msg = NULL;
int i, *ip, slot, maxslot = 0;
int i, slot, maxslot = 0;
u_int32_t bsdpartoff, cyl;
struct mbr_partition *bsdp;
/* get a buffer and initialize it */
bp = geteblk((int)lp->d_secsize);
@ -425,33 +421,74 @@ read_dos_label(dev, strat, lp, osdep)
bp->b_cylinder = MBR_BBSECTOR / lp->d_secpercyl;
(*strat)(bp);
bsdpartoff = 0;
cyl = LABELSECTOR / lp->d_secpercyl;
/* if successful, wander through dos partition table */
if (biowait(bp)) {
msg = "dos partition I/O error";
goto done;
} else {
/* XXX */
dp = (struct mbr_partition *)(bp->b_data + MBR_PARTOFF);
for (i = 0; i < NMBRPART; i++, dp++) {
if (dp->mbrp_typ != 0) {
slot = getFreeLabelEntry(lp);
if (slot > maxslot)
maxslot = slot;
pp = &lp->d_partitions[slot];
pp->p_fstype = FS_OTHER;
pp->p_offset = bswap32(dp->mbrp_start);
pp->p_size = bswap32(dp->mbrp_size);
for (ip = fat_types; *ip != -1; ip++) {
if (dp->mbrp_typ == *ip) {
pp->p_fstype = FS_MSDOS;
break;
}
}
}
}
/* XXX */
dp = (struct mbr_partition *)(bp->b_data + MBR_PARTOFF);
bsdp = NULL;
for (i = 0; i < NMBRPART; i++, dp++) {
switch (dp->mbrp_typ) {
case MBR_PTYPE_NETBSD:
bsdp = dp;
break;
case MBR_PTYPE_OPENBSD:
case MBR_PTYPE_386BSD:
if (!bsdp)
bsdp = dp;
break;
}
}
if (!bsdp) {
/* generate fake disklabel */
dp = (struct mbr_partition *)(bp->b_data + MBR_PARTOFF);
for (i = 0; i < NMBRPART; i++, dp++) {
if (!dp->mbrp_typ)
continue;
slot = getFreeLabelEntry(lp);
if (slot < 0)
break;
if (slot > maxslot)
maxslot = slot;
lp->d_partitions[slot].p_offset = bswap32(dp->mbrp_start);
lp->d_partitions[slot].p_size = bswap32(dp->mbrp_size);
switch (dp->mbrp_typ) {
case MBR_PTYPE_FAT12:
case MBR_PTYPE_FAT16S:
case MBR_PTYPE_FAT16B:
case MBR_PTYPE_FAT32:
case MBR_PTYPE_FAT32L:
case MBR_PTYPE_FAT16L:
lp->d_partitions[slot].p_fstype = FS_MSDOS;
break;
default:
lp->d_partitions[slot].p_fstype = FS_OTHER;
break;
}
}
msg = "no NetBSD disk label";
} else {
/* NetBSD partition on MBR */
bsdpartoff = bswap32(bsdp->mbrp_start);
cyl = MBR_PCYL(bsdp->mbrp_scyl, bsdp->mbrp_ssect);
lp->d_partitions[2].p_size = bswap32(bsdp->mbrp_size);
lp->d_partitions[2].p_offset = bswap32(bsdp->mbrp_start);
if (2 > maxslot)
maxslot = 2;
/* read in disklabel, blkno + 1 for DOS disklabel offset */
if (get_netbsd_label(dev, strat, lp, bsdpartoff + 1, 0))
goto done;
msg = "no NetBSD disk label";
}
lp->d_npartitions = ((maxslot >= RAW_PART) ? maxslot : RAW_PART) + 1;
done:
@ -463,11 +500,12 @@ read_dos_label(dev, strat, lp, osdep)
* Get real NetBSD disk label
*/
static int
get_netbsd_label(dev, strat, lp, bno)
get_netbsd_label(dev, strat, lp, bno, offset)
dev_t dev;
void (*strat)(struct buf *);
struct disklabel *lp;
daddr_t bno;
int offset;
{
struct buf *bp;
struct disklabel *dlp;
@ -477,7 +515,7 @@ get_netbsd_label(dev, strat, lp, bno)
bp->b_dev = dev;
/* Now get the label block */
bp->b_blkno = bno + LABELSECTOR;
bp->b_blkno = bno;
bp->b_bcount = lp->d_secsize;
bp->b_flags |= B_READ;
bp->b_cylinder = bp->b_blkno / (lp->d_secsize / DEV_BSIZE) / lp->d_secpercyl;
@ -486,7 +524,7 @@ get_netbsd_label(dev, strat, lp, bno)
if (biowait(bp))
goto done;
for (dlp = (struct disklabel *)(bp->b_data + LABELOFFSET);
for (dlp = (struct disklabel *)(bp->b_data + offset);
dlp <= (struct disklabel *)(bp->b_data + lp->d_secsize - sizeof (*dlp));
dlp = (struct disklabel *)((char *)dlp + sizeof(long))) {
if (dlp->d_magic == DISKMAGIC
@ -545,7 +583,7 @@ readdisklabel(dev, strat, lp, osdep)
if (biowait(bp))
msg = "I/O error reading block zero";
else if (get_netbsd_label(dev, strat, lp, 0))
else if (get_netbsd_label(dev, strat, lp, LABELSECTOR, LABELOFFSET))
osdep->cd_start = 0;
else {
u_int16_t *sbSigp;
@ -556,6 +594,8 @@ readdisklabel(dev, strat, lp, osdep)
} else if (bswap16(*(u_int16_t *)(bp->b_data + MBR_MAGICOFF))
== MBR_MAGIC) {
msg = read_dos_label(dev, strat, lp, osdep);
if (!msg)
osdep->cd_start = 0;
} else {
msg = "no disk label -- NetBSD or Macintosh";
osdep->cd_start = 0; /* XXX for now */

View File

@ -1,4 +1,4 @@
/* $NetBSD: disklabel_mbr.h,v 1.7 2002/03/02 07:04:31 matt Exp $ */
/* $NetBSD: disklabel_mbr.h,v 1.8 2002/06/17 15:07:06 itojun Exp $ */
/*
* Copyright (c) 1994, 1998 Christopher G. Demetriou
@ -67,6 +67,7 @@ struct mbr_partition {
/* Known MBR partition types: */
#define MBR_PTYPE_NETBSD 0xa9 /* NetBSD partition type */
#define MBR_PTYPE_OPENBSD 0xa6 /* OpenBSD partition type */
#define MBR_PTYPE_386BSD 0xa5 /* 386BSD partition type */
#define MBR_PTYPE_FAT12 0x01 /* 12-bit FAT */
#define MBR_PTYPE_FAT16S 0x04 /* 16-bit FAT, less than 32M */