summaryrefslogtreecommitdiff
path: root/sys/arch
diff options
context:
space:
mode:
authorOtto Moerbeek <otto@cvs.openbsd.org>2020-03-11 09:59:32 +0000
committerOtto Moerbeek <otto@cvs.openbsd.org>2020-03-11 09:59:32 +0000
commit84f9e4746d8ebcaadda08cea87d75c7c07cde328 (patch)
treefc166740fbf9b3d9fb0852bd009b051e00631a86 /sys/arch
parent20b4865a22981fdb4c730d8b6c144044b1f8cafc (diff)
Allow alpha boot(8) to read from an ffs2 filesystem and adapt its
custom installboot to deal with ffs2. While there, fix the partition read code to deal with offsets > 2G; ok deraadt@
Diffstat (limited to 'sys/arch')
-rw-r--r--sys/arch/alpha/stand/boot/Makefile6
-rw-r--r--sys/arch/alpha/stand/boot/filesystem.c5
-rw-r--r--sys/arch/alpha/stand/boot/version3
-rw-r--r--sys/arch/alpha/stand/installboot.c175
4 files changed, 147 insertions, 42 deletions
diff --git a/sys/arch/alpha/stand/boot/Makefile b/sys/arch/alpha/stand/boot/Makefile
index 16d551dc373..148193630bb 100644
--- a/sys/arch/alpha/stand/boot/Makefile
+++ b/sys/arch/alpha/stand/boot/Makefile
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile,v 1.24 2019/10/29 02:55:50 deraadt Exp $
+# $OpenBSD: Makefile,v 1.25 2020/03/11 09:59:31 otto Exp $
# $NetBSD: Makefile,v 1.17 1997/04/17 07:27:46 thorpej Exp $
S= ${.CURDIR}/../../../..
@@ -19,10 +19,10 @@ CLEANFILES+= vers.c vers.o ${PROG}.sym ${PROG}.nosym
.PATH: ${S}/lib/libkern/arch/alpha ${S}/lib/libkern
SRCS+= __divlu.S __remqu.S __reml.S strlen.c bzero.c __divl.S __divqu.S \
- __remlu.S
+ __remlu.S __divq.S __remq.S
.PATH: ${S}/lib/libkern/arch/alpha ${S}/lib/libsa
-SRCS+= loadfile.c arc4.c
+SRCS+= loadfile.c arc4.c ufs2.c
DEFNS= -DCOMPAT_UFS
diff --git a/sys/arch/alpha/stand/boot/filesystem.c b/sys/arch/alpha/stand/boot/filesystem.c
index eeb7e1d71ef..c7f16eebfa4 100644
--- a/sys/arch/alpha/stand/boot/filesystem.c
+++ b/sys/arch/alpha/stand/boot/filesystem.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: filesystem.c,v 1.5 2019/08/03 15:22:19 deraadt Exp $ */
+/* $OpenBSD: filesystem.c,v 1.6 2020/03/11 09:59:31 otto Exp $ */
/* $NetBSD: filesystem.c,v 1.3 1997/04/06 08:40:35 cgd Exp $ */
/*
@@ -36,11 +36,14 @@
#include <lib/libsa/stand.h>
#include <lib/libsa/ufs.h>
+#include <lib/libsa/ufs2.h>
#include <lib/libsa/cd9660.h>
struct fs_ops file_system[] = {
{ ufs_open, ufs_close, ufs_read, ufs_write,
ufs_seek, ufs_stat, ufs_readdir, ufs_fchmod },
+ { ufs2_open, ufs2_close, ufs2_read, ufs2_write,
+ ufs2_seek, ufs2_stat, ufs2_readdir, ufs2_fchmod },
{ cd9660_open, cd9660_close, cd9660_read, cd9660_write,
cd9660_seek, cd9660_stat },
};
diff --git a/sys/arch/alpha/stand/boot/version b/sys/arch/alpha/stand/boot/version
index e3c0e52f366..38c842f153b 100644
--- a/sys/arch/alpha/stand/boot/version
+++ b/sys/arch/alpha/stand/boot/version
@@ -1,4 +1,4 @@
-$OpenBSD: version,v 1.10 2014/02/19 20:52:57 miod Exp $
+$OpenBSD: version,v 1.11 2020/03/11 09:59:31 otto Exp $
$NetBSD: version,v 1.9 1997/01/23 23:10:38 cgd Exp $
1.1: Initial version
@@ -26,3 +26,4 @@ $NetBSD: version,v 1.9 1997/01/23 23:10:38 cgd Exp $
1.8: Use MI loadfile, warn if kernel image would overlap SRM
1.9: Better PALcode switching sequence
1.10: /etc/random.seed support
+1.11: ffs2 support
diff --git a/sys/arch/alpha/stand/installboot.c b/sys/arch/alpha/stand/installboot.c
index 96f6f2978d4..767b96f7fcd 100644
--- a/sys/arch/alpha/stand/installboot.c
+++ b/sys/arch/alpha/stand/installboot.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: installboot.c,v 1.19 2014/07/12 19:01:49 tedu Exp $ */
+/* $OpenBSD: installboot.c,v 1.20 2020/03/11 09:59:31 otto Exp $ */
/* $NetBSD: installboot.c,v 1.2 1997/04/06 08:41:12 cgd Exp $ */
/*
@@ -68,13 +68,17 @@ int max_block_count;
char *loadprotoblocks(char *, long *);
int loadblocknums(char *, int, unsigned long);
-static void devread(int, void *, daddr32_t, size_t, char *);
+static void devread(int, void *, daddr_t, size_t, char *);
static void usage(void);
+static int sbchk(struct fs *, daddr_t);
+static void sbread(int, daddr_t, struct fs **, char *);
int main(int, char *[]);
int isofsblk = 0;
int isofseblk = 0;
+static const daddr_t sbtry[] = SBLOCKSEARCH;
+
static void
usage(void)
{
@@ -183,7 +187,7 @@ main(int argc, char *argv[])
sync();
sleep(2);
- if (loadblocknums(boot, devfd, partoffset) != 0)
+ if (loadblocknums(boot, devfd, DL_SECTOBLK(&dl, partoffset)) != 0)
exit(1);
(void)close(devfd);
@@ -302,13 +306,10 @@ loadprotoblocks(char *fname, long *size)
}
static void
-devread(int fd, void *buf, daddr32_t blk, size_t size, char *msg)
+devread(int fd, void *buf, daddr_t blk, size_t size, char *msg)
{
- if (lseek(fd, dbtob(blk), SEEK_SET) != dbtob(blk))
- err(1, "%s: devread: lseek", msg);
-
- if (read(fd, buf, size) != size)
- err(1, "%s: devread: read", msg);
+ if (pread(fd, buf, size, dbtob((off_t)blk)) != (ssize_t)size)
+ err(1, "%s: devread: pread", msg);
}
static char sblock[SBSIZE];
@@ -321,8 +322,10 @@ loadblocknums(char *boot, int devfd, unsigned long partoffset)
struct statfs statfsbuf;
struct fs *fs;
char *buf;
- daddr32_t blk, *ap;
- struct ufs1_dinode *ip;
+ daddr32_t *ap1;
+ daddr_t blk, *ap2;
+ struct ufs1_dinode *ip1;
+ struct ufs2_dinode *ip2;
int32_t cksum;
/*
@@ -373,9 +376,7 @@ loadblocknums(char *boot, int devfd, unsigned long partoffset)
close(fd);
/* Read superblock */
- devread(devfd, sblock, btodb(SBOFF) + partoffset, SBSIZE,
- "superblock");
- fs = (struct fs *)sblock;
+ sbread(devfd, partoffset, &fs, sblock);
/* Read inode */
if ((buf = malloc(fs->fs_bsize)) == NULL)
@@ -383,19 +384,25 @@ loadblocknums(char *boot, int devfd, unsigned long partoffset)
blk = fsbtodb(fs, ino_to_fsba(fs, statbuf.st_ino));
devread(devfd, buf, blk + partoffset, fs->fs_bsize, "inode");
- ip = (struct ufs1_dinode *)(buf) + ino_to_fsbo(fs, statbuf.st_ino);
-
+ if (fs->fs_magic == FS_UFS1_MAGIC) {
+ ip1 = (struct ufs1_dinode *)(buf) + ino_to_fsbo(fs,
+ statbuf.st_ino);
+ ndb = howmany(ip1->di_size, fs->fs_bsize);
+ } else {
+ ip2 = (struct ufs2_dinode *)(buf) + ino_to_fsbo(fs,
+ statbuf.st_ino);
+ ndb = howmany(ip2->di_size, fs->fs_bsize);
+ }
/*
- * Register filesystem block size.
+ * Check the block numbers; we don't handle fragments
*/
- bbinfop->bsize = fs->fs_bsize;
+ if (ndb > max_block_count)
+ errx(1, "%s: Too many blocks", boot);
/*
- * Get the block numbers; we don't handle fragments
+ * Register filesystem block size.
*/
- ndb = howmany(ip->di_size, fs->fs_bsize);
- if (ndb > max_block_count)
- errx(1, "%s: Too many blocks", boot);
+ bbinfop->bsize = fs->fs_bsize;
/*
* Register block count.
@@ -404,12 +411,22 @@ loadblocknums(char *boot, int devfd, unsigned long partoffset)
if (verbose)
(void)printf("%s: block numbers: ", boot);
- ap = ip->di_db;
- for (i = 0; i < NDADDR && *ap && ndb; i++, ap++, ndb--) {
- blk = fsbtodb(fs, *ap);
- bbinfop->blocks[i] = blk + partoffset;
- if (verbose)
- (void)printf("%d ", bbinfop->blocks[i]);
+ if (fs->fs_magic == FS_UFS1_MAGIC) {
+ ap1 = ip1->di_db;
+ for (i = 0; i < NDADDR && *ap1 && ndb; i++, ap1++, ndb--) {
+ blk = fsbtodb(fs, *ap1);
+ bbinfop->blocks[i] = blk + partoffset;
+ if (verbose)
+ (void)printf("%d ", bbinfop->blocks[i]);
+ }
+ } else {
+ ap2 = ip2->di_db;
+ for (i = 0; i < NDADDR && *ap2 && ndb; i++, ap2++, ndb--) {
+ blk = fsbtodb(fs, *ap2);
+ bbinfop->blocks[i] = blk + partoffset;
+ if (verbose)
+ (void)printf("%d ", bbinfop->blocks[i]);
+ }
}
if (verbose)
(void)printf("\n");
@@ -423,15 +440,28 @@ loadblocknums(char *boot, int devfd, unsigned long partoffset)
*/
if (verbose)
(void)printf("%s: block numbers (indirect): ", boot);
- blk = ip->di_ib[0];
- devread(devfd, buf, blk + partoffset, fs->fs_bsize,
- "indirect block");
- ap = (daddr32_t *)buf;
- for (; i < NINDIR(fs) && *ap && ndb; i++, ap++, ndb--) {
- blk = fsbtodb(fs, *ap);
- bbinfop->blocks[i] = blk + partoffset;
- if (verbose)
- (void)printf("%d ", bbinfop->blocks[i]);
+ if (fs->fs_magic == FS_UFS1_MAGIC) {
+ blk = ip1->di_ib[0];
+ devread(devfd, buf, blk + partoffset, fs->fs_bsize,
+ "indirect block");
+ ap1 = (daddr32_t *)buf;
+ for (; i < NINDIR(fs) && *ap1 && ndb; i++, ap1++, ndb--) {
+ blk = fsbtodb(fs, *ap1);
+ bbinfop->blocks[i] = blk + partoffset;
+ if (verbose)
+ (void)printf("%d ", bbinfop->blocks[i]);
+ }
+ } else {
+ blk = ip2->di_ib[0];
+ devread(devfd, buf, blk + partoffset, fs->fs_bsize,
+ "indirect block");
+ ap2 = (daddr_t *)buf;
+ for (; i < NINDIR(fs) && *ap2 && ndb; i++, ap2++, ndb--) {
+ blk = fsbtodb(fs, *ap2);
+ bbinfop->blocks[i] = blk + partoffset;
+ if (verbose)
+ (void)printf("%d ", bbinfop->blocks[i]);
+ }
}
if (verbose)
(void)printf("\n");
@@ -448,3 +478,74 @@ checksum:
return 0;
}
+
+static int
+sbchk(struct fs *fs, daddr_t sbloc)
+{
+ if (verbose)
+ fprintf(stderr, "looking for superblock at %lld\n", sbloc);
+
+ if (fs->fs_magic != FS_UFS2_MAGIC && fs->fs_magic != FS_UFS1_MAGIC) {
+ if (verbose)
+ fprintf(stderr, "bad superblock magic 0x%x\n",
+ fs->fs_magic);
+ return (0);
+ }
+
+ /*
+ * Looking for an FFS1 file system at SBLOCK_UFS2 will find the
+ * wrong superblock for file systems with 64k block size.
+ */
+ if (fs->fs_magic == FS_UFS1_MAGIC && sbloc == SBLOCK_UFS2) {
+ if (verbose)
+ fprintf(stderr, "skipping ffs1 superblock at %lld\n",
+ sbloc);
+ return (0);
+ }
+
+ if (fs->fs_bsize <= 0 || fs->fs_bsize < sizeof(struct fs) ||
+ fs->fs_bsize > MAXBSIZE) {
+ if (verbose)
+ fprintf(stderr, "invalid superblock block size %d\n",
+ fs->fs_bsize);
+ return (0);
+ }
+
+ if (fs->fs_sbsize <= 0 || fs->fs_sbsize > SBSIZE) {
+ if (verbose)
+ fprintf(stderr, "invalid superblock size %d\n",
+ fs->fs_sbsize);
+ return (0);
+ }
+
+ if (fs->fs_inopb <= 0) {
+ if (verbose)
+ fprintf(stderr, "invalid superblock inodes/block %d\n",
+ fs->fs_inopb);
+ return (0);
+ }
+
+ if (verbose)
+ fprintf(stderr, "found valid %s superblock\n",
+ fs->fs_magic == FS_UFS2_MAGIC ? "ffs2" : "ffs1");
+
+ return (1);
+}
+
+static void
+sbread(int fd, daddr_t poffset, struct fs **fs, char *sblock)
+{
+ int i;
+ daddr_t sboff;
+
+ for (i = 0; sbtry[i] != -1; i++) {
+ sboff = sbtry[i] / DEV_BSIZE;
+ devread(fd, sblock, poffset + sboff, SBSIZE, "superblock");
+ *fs = (struct fs *)sblock;
+ if (sbchk(*fs, sbtry[i]))
+ break;
+ }
+
+ if (sbtry[i] == -1)
+ errx(1, "couldn't find ffs superblock");
+}