summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkrw <krw@openbsd.org>2011-07-05 17:38:54 +0000
committerkrw <krw@openbsd.org>2011-07-05 17:38:54 +0000
commitef93a5ee996b0931488d1007888915a83cd0701b (patch)
tree72c5178c95f53b646c90697893d823208fccd3d5
parentN: Thou shalt not call hardclock() with biglock held. (diff)
downloadwireguard-openbsd-ef93a5ee996b0931488d1007888915a83cd0701b.tar.xz
wireguard-openbsd-ef93a5ee996b0931488d1007888915a83cd0701b.zip
More non-512-byte sector groundwork. Don't let disklabel hint that
a ffs frag size can be less than the d_secsize of the disk. Make sure amd64 writedisklabel() puts the disklabel where readdoslabel() will read it. Tweak i386/amd64 installboot/biosboot so sectors are indeed used where sectors are claimed. Lets me fdisk, newfs, mount and installboot onto 2048 and 4096 byte sector devices. Other filesystem utilites will still hold surprises. Note that actually booting from such devices will await BIOSen that acknowledge such devices as bootable. ok guenther@
-rw-r--r--sbin/disklabel/editor.c5
-rw-r--r--sys/arch/amd64/amd64/disksubr.c9
-rw-r--r--sys/arch/amd64/stand/biosboot/biosboot.S6
-rw-r--r--sys/arch/amd64/stand/installboot/installboot.c45
-rw-r--r--sys/arch/i386/stand/biosboot/biosboot.S6
-rw-r--r--sys/arch/i386/stand/installboot/installboot.c49
6 files changed, 86 insertions, 34 deletions
diff --git a/sbin/disklabel/editor.c b/sbin/disklabel/editor.c
index 10b77db8ab6..cf23efbefe5 100644
--- a/sbin/disklabel/editor.c
+++ b/sbin/disklabel/editor.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: editor.c,v 1.256 2011/05/24 15:27:56 otto Exp $ */
+/* $OpenBSD: editor.c,v 1.257 2011/07/05 17:38:54 krw Exp $ */
/*
* Copyright (c) 1997-2000 Todd C. Miller <Todd.Miller@courtesan.com>
@@ -667,7 +667,8 @@ cylinderalign:
/* Everything seems ok so configure the partition. */
DL_SETPSIZE(pp, secs);
DL_SETPOFFSET(pp, chunkstart);
- fragsize = 2048;
+ fragsize = (lp->d_secsize == DEV_BSIZE) ? 2048 :
+ lp->d_secsize;
if (secs * lp->d_secsize > 128ULL * 1024 * 1024 * 1024)
fragsize *= 2;
if (secs * lp->d_secsize > 512ULL * 1024 * 1024 * 1024)
diff --git a/sys/arch/amd64/amd64/disksubr.c b/sys/arch/amd64/amd64/disksubr.c
index 61808336522..f6988fa3d3d 100644
--- a/sys/arch/amd64/amd64/disksubr.c
+++ b/sys/arch/amd64/amd64/disksubr.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: disksubr.c,v 1.61 2011/04/16 03:21:15 krw Exp $ */
+/* $OpenBSD: disksubr.c,v 1.62 2011/07/05 17:38:54 krw Exp $ */
/* $NetBSD: disksubr.c,v 1.21 1996/05/03 19:42:03 christos Exp $ */
/*
@@ -122,6 +122,7 @@ int
writedisklabel(dev_t dev, void (*strat)(struct buf *), struct disklabel *lp)
{
int error = EIO, partoff = -1;
+ int offset;
struct disklabel *dlp;
struct buf *bp = NULL;
@@ -133,15 +134,15 @@ writedisklabel(dev_t dev, void (*strat)(struct buf *), struct disklabel *lp)
goto done;
/* Read it in, slap the new label in, and write it back out */
- bp->b_blkno = partoff + LABELSECTOR;
- bp->b_bcount = lp->d_secsize;
+ bp->b_blkno = DL_BLKTOSEC(lp, partoff+LABELSECTOR) * DL_BLKSPERSEC(lp);
+ offset = DL_BLKOFFSET(lp, partoff + LABELSECTOR) + LABELOFFSET;
CLR(bp->b_flags, B_READ | B_WRITE | B_DONE);
SET(bp->b_flags, B_BUSY | B_READ | B_RAW);
(*strat)(bp);
if ((error = biowait(bp)) != 0)
goto done;
- dlp = (struct disklabel *)(bp->b_data + LABELOFFSET);
+ dlp = (struct disklabel *)(bp->b_data + offset);
*dlp = *lp;
CLR(bp->b_flags, B_READ | B_WRITE | B_DONE);
SET(bp->b_flags, B_BUSY | B_WRITE | B_RAW);
diff --git a/sys/arch/amd64/stand/biosboot/biosboot.S b/sys/arch/amd64/stand/biosboot/biosboot.S
index e3dcbd147f4..0042a89ee36 100644
--- a/sys/arch/amd64/stand/biosboot/biosboot.S
+++ b/sys/arch/amd64/stand/biosboot/biosboot.S
@@ -1,4 +1,4 @@
-/* $OpenBSD: biosboot.S,v 1.6 2010/07/09 17:36:38 deraadt Exp $ */
+/* $OpenBSD: biosboot.S,v 1.7 2011/07/05 17:38:54 krw Exp $ */
/*
* Copyright (c) 2003 Tobias Weingartner
@@ -91,8 +91,8 @@
* where we load the block to.)
* fs_bsize_p uint16 the filesystem block size _in paragraphs_
* (i.e. fs_bsize / 16)
- * fs_bsize_s uint16 the number of 512-byte sectors in a filesystem
- * block (i.e. fs_bsize / 512). Directly written
+ * fs_bsize_s uint16 the number of disk sectors in a filesystem
+ * block (i.e. fs_bsize / d_secsize). Directly written
* into the LBA command block, at lba_count.
* XXX LIMITED TO 127 BY PHOENIX EDD SPEC.
* fsbtodb uint8 shift count to convert filesystem blocks to
diff --git a/sys/arch/amd64/stand/installboot/installboot.c b/sys/arch/amd64/stand/installboot/installboot.c
index 6f1dd7ee291..1877b07bbdd 100644
--- a/sys/arch/amd64/stand/installboot/installboot.c
+++ b/sys/arch/amd64/stand/installboot/installboot.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: installboot.c,v 1.20 2011/07/03 19:21:48 krw Exp $ */
+/* $OpenBSD: installboot.c,v 1.21 2011/07/05 17:38:54 krw Exp $ */
/* $NetBSD: installboot.c,v 1.5 1995/11/17 23:23:50 gwr Exp $ */
/*
@@ -215,6 +215,7 @@ void
write_bootblocks(int devfd, struct disklabel *dl)
{
struct stat sb;
+ u_int8_t *secbuf;
u_int start = 0;
/* Write patched proto bootblock(s) into the superblock. */
@@ -240,7 +241,7 @@ write_bootblocks(int devfd, struct disklabel *dl)
errx(1, "no OpenBSD partition");
}
- if (start + (protosize / DEV_BSIZE) > BOOTBIOS_MAXSEC)
+ if (start + (protosize / dl->d_secsize) > BOOTBIOS_MAXSEC)
errx(1, "invalid location: all of /boot must be < sector %u.",
BOOTBIOS_MAXSEC);
@@ -248,9 +249,13 @@ write_bootblocks(int devfd, struct disklabel *dl)
fprintf(stderr, "/boot will be written at sector %u\n", start);
if (!nowrite) {
- if (lseek(devfd, (off_t)start * dl->d_secsize, SEEK_SET) < 0 ||
- write(devfd, protostore, protosize) != protosize)
+ if (lseek(devfd, (off_t)start * dl->d_secsize, SEEK_SET) < 0)
+ err(1, "seek bootstrap");
+ secbuf = calloc(1, dl->d_secsize);
+ bcopy(protostore, secbuf, protosize);
+ if (write(devfd, secbuf, dl->d_secsize) != dl->d_secsize)
err(1, "write bootstrap");
+ free(secbuf);
}
}
@@ -261,6 +266,7 @@ findopenbsd(int devfd, struct disklabel *dl)
u_int mbroff = DOSBBSECTOR;
u_int mbr_eoff = DOSBBSECTOR; /* Offset of extended part. */
struct dos_partition *dp;
+ u_int8_t *secbuf;
int i, maxebr = DOS_MAXEBR, nextebr;
again:
@@ -277,9 +283,12 @@ again:
(mbroff == DOSBBSECTOR) ? "master" : "extended",
(mbroff == DOSBBSECTOR) ? 'M' : 'E', mbroff);
+ secbuf = malloc(dl->d_secsize);
if (lseek(devfd, (off_t)mbroff * dl->d_secsize, SEEK_SET) < 0 ||
- read(devfd, &mbr, sizeof(mbr)) != sizeof(mbr))
+ read(devfd, secbuf, dl->d_secsize) < sizeof(mbr))
err(4, "can't read boot record");
+ bcopy(secbuf, &mbr, sizeof(mbr));
+ free(secbuf);
if (mbr.dmbr_sign != DOSMBR_SIGNATURE)
errx(1, "invalid boot record signature (0x%04X) @ sector %u",
@@ -477,7 +486,8 @@ getbootparams(char *boot, int devfd, struct disklabel *dl)
close(fd);
/* Read superblock. */
- devread(devfd, sblock, pp->p_offset + SBLOCK, SBSIZE, "superblock");
+ devread(devfd, sblock, DL_SECTOBLK(dl, pp->p_offset) + SBLOCK,
+ SBSIZE, "superblock");
fs = (struct fs *)sblock;
/* Sanity-check super-block. */
@@ -492,7 +502,8 @@ getbootparams(char *boot, int devfd, struct disklabel *dl)
blk = fsbtodb(fs, ino_to_fsba(fs, statbuf.st_ino));
- devread(devfd, buf, pp->p_offset + blk, fs->fs_bsize, "inode");
+ devread(devfd, buf, DL_SECTOBLK(dl, pp->p_offset) + blk,
+ fs->fs_bsize, "inode");
ip = (struct ufs1_dinode *)(buf) + ino_to_fsbo(fs, statbuf.st_ino);
/*
@@ -508,8 +519,21 @@ getbootparams(char *boot, int devfd, struct disklabel *dl)
* (the partition boot record, a.k.a. the PBR).
*/
sym_set_value(pbr_symbols, "_fs_bsize_p", (fs->fs_bsize / 16));
- sym_set_value(pbr_symbols, "_fs_bsize_s", (fs->fs_bsize / 512));
- sym_set_value(pbr_symbols, "_fsbtodb", fs->fs_fsbtodb);
+ sym_set_value(pbr_symbols, "_fs_bsize_s", (fs->fs_bsize /
+ dl->d_secsize));
+
+ /*
+ * fs_fsbtodb is the shift to convert fs_fsize to DEV_BSIZE. The
+ * ino_to_fsba() return value is the number of fs_fsize units.
+ * Calculate the shift to convert fs_fsize into physical sectors,
+ * which are added to p_offset to get the sector address BIOS
+ * will use.
+ *
+ * N.B.: ASSUMES fs_fsize is a power of 2 of d_secsize.
+ */
+ sym_set_value(pbr_symbols, "_fsbtodb",
+ ffs(fs->fs_fsize / dl->d_secsize) - 1);
+
sym_set_value(pbr_symbols, "_p_offset", pp->p_offset);
sym_set_value(pbr_symbols, "_inodeblk",
ino_to_fsba(fs, statbuf.st_ino));
@@ -523,7 +547,8 @@ getbootparams(char *boot, int devfd, struct disklabel *dl)
boot, ndb, fs->fs_bsize);
fprintf(stderr, "fs block shift %u; part offset %u; "
"inode block %lld, offset %u\n",
- fs->fs_fsbtodb, pp->p_offset,
+ ffs(fs->fs_fsize / dl->d_secsize) - 1,
+ pp->p_offset,
ino_to_fsba(fs, statbuf.st_ino),
(unsigned int)((((char *)ap) - buf) + INODEOFF));
}
diff --git a/sys/arch/i386/stand/biosboot/biosboot.S b/sys/arch/i386/stand/biosboot/biosboot.S
index cd6e7f90341..36ccd54d53f 100644
--- a/sys/arch/i386/stand/biosboot/biosboot.S
+++ b/sys/arch/i386/stand/biosboot/biosboot.S
@@ -1,4 +1,4 @@
-/* $OpenBSD: biosboot.S,v 1.40 2009/09/30 19:03:17 weingart Exp $ */
+/* $OpenBSD: biosboot.S,v 1.41 2011/07/05 17:38:54 krw Exp $ */
/*
* Copyright (c) 2003 Tobias Weingartner
@@ -91,8 +91,8 @@
* where we load the block to.)
* fs_bsize_p uint16 the filesystem block size _in paragraphs_
* (i.e. fs_bsize / 16)
- * fs_bsize_s uint16 the number of 512-byte sectors in a filesystem
- * block (i.e. fs_bsize / 512). Directly written
+ * fs_bsize_s uint16 the number of disk sectors in a filesystem
+ * block (i.e. fs_bsize / d_secsize). Directly written
* into the LBA command block, at lba_count.
* XXX LIMITED TO 127 BY PHOENIX EDD SPEC.
* fsbtodb uint8 shift count to convert filesystem blocks to
diff --git a/sys/arch/i386/stand/installboot/installboot.c b/sys/arch/i386/stand/installboot/installboot.c
index 3d88a929471..cf43ed3a60e 100644
--- a/sys/arch/i386/stand/installboot/installboot.c
+++ b/sys/arch/i386/stand/installboot/installboot.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: installboot.c,v 1.63 2011/07/03 19:21:48 krw Exp $ */
+/* $OpenBSD: installboot.c,v 1.64 2011/07/05 17:38:54 krw Exp $ */
/* $NetBSD: installboot.c,v 1.5 1995/11/17 23:23:50 gwr Exp $ */
/*
@@ -211,6 +211,7 @@ void
write_bootblocks(int devfd, struct disklabel *dl)
{
struct stat sb;
+ u_int8_t *secbuf;
u_int start = 0;
/* Write patched proto bootblock(s) into the superblock. */
@@ -236,7 +237,7 @@ write_bootblocks(int devfd, struct disklabel *dl)
errx(1, "no OpenBSD partition");
}
- if (start + (protosize / DEV_BSIZE) > BOOTBIOS_MAXSEC)
+ if (start + (protosize / dl->d_secsize) > BOOTBIOS_MAXSEC)
errx(1, "invalid location: all of /boot must be < sector %u.",
BOOTBIOS_MAXSEC);
@@ -244,9 +245,13 @@ write_bootblocks(int devfd, struct disklabel *dl)
fprintf(stderr, "/boot will be written at sector %u\n", start);
if (!nowrite) {
- if (lseek(devfd, (off_t)start * dl->d_secsize, SEEK_SET) < 0 ||
- write(devfd, protostore, protosize) != protosize)
+ if (lseek(devfd, (off_t)start * dl->d_secsize, SEEK_SET) < 0)
+ err(1, "seek bootstrap");
+ secbuf = calloc(1, dl->d_secsize);
+ bcopy(protostore, secbuf, protosize);
+ if (write(devfd, secbuf, dl->d_secsize) != dl->d_secsize)
err(1, "write bootstrap");
+ free(secbuf);
}
}
@@ -257,6 +262,7 @@ findopenbsd(int devfd, struct disklabel *dl)
u_int mbroff = DOSBBSECTOR;
u_int mbr_eoff = DOSBBSECTOR; /* Offset of extended part. */
struct dos_partition *dp;
+ u_int8_t *secbuf;
int i, maxebr = DOS_MAXEBR, nextebr;
again:
@@ -273,9 +279,12 @@ again:
(mbroff == DOSBBSECTOR) ? "master" : "extended",
(mbroff == DOSBBSECTOR) ? 'M' : 'E', mbroff);
+ secbuf = malloc(dl->d_secsize);
if (lseek(devfd, (off_t)mbroff * dl->d_secsize, SEEK_SET) < 0 ||
- read(devfd, &mbr, sizeof(mbr)) != sizeof(mbr))
+ read(devfd, secbuf, dl->d_secsize) < sizeof(mbr))
err(4, "can't read boot record");
+ bcopy(secbuf, &mbr, sizeof(mbr));
+ free(secbuf);
if (mbr.dmbr_sign != DOSMBR_SIGNATURE)
errx(1, "invalid boot record signature (0x%04X) @ sector %u",
@@ -473,7 +482,8 @@ getbootparams(char *boot, int devfd, struct disklabel *dl)
close(fd);
/* Read superblock. */
- devread(devfd, sblock, pp->p_offset + SBLOCK, SBSIZE, "superblock");
+ devread(devfd, sblock, DL_SECTOBLK(dl, pp->p_offset) + SBLOCK,
+ SBSIZE, "superblock");
fs = (struct fs *)sblock;
/* Sanity-check super-block. */
@@ -488,7 +498,8 @@ getbootparams(char *boot, int devfd, struct disklabel *dl)
blk = fsbtodb(fs, ino_to_fsba(fs, statbuf.st_ino));
- devread(devfd, buf, pp->p_offset + blk, fs->fs_bsize, "inode");
+ devread(devfd, buf, DL_SECTOBLK(dl, pp->p_offset) + blk,
+ fs->fs_bsize, "inode");
ip = (struct ufs1_dinode *)(buf) + ino_to_fsbo(fs, statbuf.st_ino);
/*
@@ -504,8 +515,21 @@ getbootparams(char *boot, int devfd, struct disklabel *dl)
* (the partition boot record, a.k.a. the PBR).
*/
sym_set_value(pbr_symbols, "_fs_bsize_p", (fs->fs_bsize / 16));
- sym_set_value(pbr_symbols, "_fs_bsize_s", (fs->fs_bsize / 512));
- sym_set_value(pbr_symbols, "_fsbtodb", fs->fs_fsbtodb);
+ sym_set_value(pbr_symbols, "_fs_bsize_s", (fs->fs_bsize /
+ dl->d_secsize));
+
+ /*
+ * fs_fsbtodb is the shift to convert fs_fsize to DEV_BSIZE. The
+ * ino_to_fsba() return value is the number of fs_fsize units.
+ * Calculate the shift to convert fs_fsize into physical sectors,
+ * which are added to p_offset to get the sector address BIOS
+ * will use.
+ *
+ * N.B.: ASSUMES fs_fsize is a power of 2 of d_secsize.
+ */
+ sym_set_value(pbr_symbols, "_fsbtodb",
+ ffs(fs->fs_fsize / dl->d_secsize) - 1);
+
sym_set_value(pbr_symbols, "_p_offset", pp->p_offset);
sym_set_value(pbr_symbols, "_inodeblk",
ino_to_fsba(fs, statbuf.st_ino));
@@ -518,10 +542,11 @@ getbootparams(char *boot, int devfd, struct disklabel *dl)
fprintf(stderr, "%s is %d blocks x %d bytes\n",
boot, ndb, fs->fs_bsize);
fprintf(stderr, "fs block shift %u; part offset %u; "
- "inode block %lld, offset %ld\n",
- fs->fs_fsbtodb, pp->p_offset,
+ "inode block %lld, offset %u\n",
+ ffs(fs->fs_fsize / dl->d_secsize) - 1,
+ pp->p_offset,
ino_to_fsba(fs, statbuf.st_ino),
- ((((char *)ap) - buf) + INODEOFF));
+ (unsigned int)((((char *)ap) - buf) + INODEOFF));
}
return 0;