summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/boot/ofw/libofw/devicename.c22
-rw-r--r--sys/boot/sparc64/Makefile2
-rw-r--r--sys/boot/sparc64/boot1/Makefile9
-rw-r--r--sys/boot/sparc64/boot1/boot1.c136
-rw-r--r--sys/boot/sparc64/loader/Makefile22
-rw-r--r--sys/boot/sparc64/loader/main.c109
-rw-r--r--sys/boot/sparc64/zfsboot/Makefile13
-rw-r--r--sys/boot/sparc64/zfsloader/Makefile9
-rw-r--r--sys/boot/zfs/zfs.c2
9 files changed, 281 insertions, 43 deletions
diff --git a/sys/boot/ofw/libofw/devicename.c b/sys/boot/ofw/libofw/devicename.c
index 3cae23c..c2d9ef1 100644
--- a/sys/boot/ofw/libofw/devicename.c
+++ b/sys/boot/ofw/libofw/devicename.c
@@ -28,6 +28,8 @@
__FBSDID("$FreeBSD$");
#include <stand.h>
+
+#include "bootstrap.h"
#include "libofw.h"
static int ofw_parsedev(struct ofw_devdesc **, const char *, const char **);
@@ -76,6 +78,7 @@ ofw_parsedev(struct ofw_devdesc **dev, const char *devspec, const char **path)
phandle_t handle;
const char *p;
const char *s;
+ char *ep;
char name[256];
char type[64];
int len;
@@ -87,9 +90,10 @@ ofw_parsedev(struct ofw_devdesc **dev, const char *devspec, const char **path)
len = s - devspec;
bcopy(devspec, name, len);
name[len] = '\0';
- if ((handle = OF_finddevice(name)) == -1)
- break;
- if (OF_getprop(handle, "device_type", type, sizeof(type)) == -1)
+ if ((handle = OF_finddevice(name)) == -1) {
+ bcopy(name, type, len);
+ type[len] = '\0';
+ } else if (OF_getprop(handle, "device_type", type, sizeof(type)) == -1)
continue;
for (i = 0; (dv = devsw[i]) != NULL; i++) {
if (strncmp(dv->dv_name, type, strlen(dv->dv_name)) == 0)
@@ -109,6 +113,18 @@ found:
strcpy(idev->d_path, name);
idev->d_dev = dv;
idev->d_type = dv->dv_type;
+ if (idev->d_type == DEVT_ZFS) {
+ idev->d_unit = 0;
+ p = name + strlen(dv->dv_name);
+ if (*p && (*p != ':')) {
+ idev->d_unit = strtol(p, &ep, 0);
+ if (ep == p) {
+ free(idev);
+ return (EUNIT);
+ }
+ }
+ }
+
if (dev == NULL) {
free(idev);
} else {
diff --git a/sys/boot/sparc64/Makefile b/sys/boot/sparc64/Makefile
index fdc87fd..a768039 100644
--- a/sys/boot/sparc64/Makefile
+++ b/sys/boot/sparc64/Makefile
@@ -1,5 +1,5 @@
# $FreeBSD$
-SUBDIR= boot1 loader
+SUBDIR= boot1 loader zfsboot zfsloader
.include <bsd.subdir.mk>
diff --git a/sys/boot/sparc64/boot1/Makefile b/sys/boot/sparc64/boot1/Makefile
index dec3e09..9a97400 100644
--- a/sys/boot/sparc64/boot1/Makefile
+++ b/sys/boot/sparc64/boot1/Makefile
@@ -3,22 +3,23 @@
PROG= boot1.elf
INTERNALPROG=
NO_MAN=
-FILES= boot1
+FILES?= boot1
SRCS= _start.s boot1.c
+CLEANFILES+=boot1 boot1.aout
BOOTBLOCKBASE= 0x4000
-CFLAGS= -mcmodel=medlow -Os -I${.CURDIR}/../../common
+CFLAGS+=-mcmodel=medlow -Os -I${.CURDIR}/../../common
LDFLAGS=-Ttext ${BOOTBLOCKBASE} -Wl,-N
# Construct boot1. sunlabel expects it to contain zeroed-out space for the
# label, and to be of the correct size.
boot1: boot1.aout
+ @set -- `ls -l boot1.aout`; x=$$((7680-$$5)); \
+ echo "$$x bytes available"; test $$x -ge 0
dd if=/dev/zero of=${.TARGET} bs=512 count=16
dd if=boot1.aout of=${.TARGET} bs=512 oseek=1 conv=notrunc
-CLEANFILES= boot1.aout
-
boot1.aout: boot1.elf
elf2aout -o ${.TARGET} ${.ALLSRC}
diff --git a/sys/boot/sparc64/boot1/boot1.c b/sys/boot/sparc64/boot1/boot1.c
index 6b9fa30..685d414 100644
--- a/sys/boot/sparc64/boot1/boot1.c
+++ b/sys/boot/sparc64/boot1/boot1.c
@@ -20,11 +20,13 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/dirent.h>
+
#include <machine/elf.h>
#include <machine/stdarg.h>
-#define _PATH_LOADER "/boot/loader"
-#define _PATH_KERNEL "/boot/kernel/kernel"
+#define _PATH_LOADER "/boot/loader"
+#define _PATH_KERNEL "/boot/kernel/kernel"
+#define READ_BUF_SIZE 8192
typedef int putc_func_t(char c, void *arg);
typedef int32_t ofwh_t;
@@ -45,17 +47,21 @@ static ofwh_t bootdev;
static uint32_t fs_off;
int main(int ac, char **av);
-
static void exit(int) __dead2;
-static void load(const char *);
-static int dskread(void *, u_int64_t, int);
-
static void usage(void);
+#ifdef ZFSBOOT
+static void loadzfs(void);
+static int zbread(char *buf, off_t off, size_t bytes);
+#else
+static void load(const char *);
+#endif
+
static void bcopy(const void *src, void *dst, size_t len);
static void bzero(void *b, size_t len);
static int mount(const char *device);
+static int dskread(void *buf, u_int64_t lba, int nblk);
static void panic(const char *fmt, ...) __dead2;
static int printf(const char *fmt, ...);
@@ -312,8 +318,6 @@ strcmp(const char *s1, const char *s2)
return ((u_char)*s1 - (u_char)*s2);
}
-#include "ufsread.c"
-
int
main(int ac, char **av)
{
@@ -335,14 +339,22 @@ main(int ac, char **av)
}
}
- printf(" \n>> FreeBSD/sparc64 boot block\n"
- " Boot path: %s\n"
- " Boot loader: %s\n", bootpath, path);
+#ifdef ZFSBOOT
+ printf(" \n>> FreeBSD/sparc64 ZFS boot block\n Boot path: %s\n",
+ bootpath);
+#else
+ printf(" \n>> FreeBSD/sparc64 boot block\n Boot path: %s\n"
+ " Boot loader: %s\n", "", bootpath, path);
+#endif
if (mount(bootpath) == -1)
panic("mount");
+#ifdef ZFSBOOT
+ loadzfs();
+#else
load(path);
+#endif
return (1);
}
@@ -361,24 +373,86 @@ exit(int code)
ofw_exit();
}
-static struct dmadat __dmadat;
+#ifdef ZFSBOOT
+
+#define VDEV_BOOT_OFFSET (2 * 256 * 1024)
+static char zbuf[READ_BUF_SIZE];
static int
-mount(const char *device)
+zbread(char *buf, off_t off, size_t bytes)
{
+ size_t len;
+ off_t poff;
+ off_t soff;
+ char *p;
+ unsigned int nb;
+ unsigned int lb;
- dmadat = &__dmadat;
- if ((bootdev = ofw_open(device)) == -1) {
- printf("mount: can't open device\n");
- return (-1);
+ p = buf;
+ soff = VDEV_BOOT_OFFSET + off;
+ lb = (soff + bytes + DEV_BSIZE - 1) / DEV_BSIZE;
+ poff = soff;
+ while (poff < soff + bytes) {
+ nb = lb - poff / DEV_BSIZE;
+ if (nb > READ_BUF_SIZE / DEV_BSIZE)
+ nb = READ_BUF_SIZE / DEV_BSIZE;
+ if (dskread(zbuf, poff / DEV_BSIZE, nb))
+ break;
+ if ((poff / DEV_BSIZE + nb) * DEV_BSIZE > soff + bytes)
+ len = soff + bytes - poff;
+ else
+ len = (poff / DEV_BSIZE + nb) * DEV_BSIZE - poff;
+ memcpy(p, zbuf + poff % DEV_BSIZE, len);
+ p += len;
+ poff += len;
}
- if (fsread(0, NULL, 0)) {
- printf("mount: can't read superblock\n");
- return (-1);
+ return (poff - soff);
+}
+
+static void
+loadzfs(void)
+{
+ Elf64_Ehdr eh;
+ Elf64_Phdr ph;
+ caddr_t p;
+ ino_t ino;
+ int i;
+
+ if (zbread((char *)&eh, 0, sizeof(eh)) != sizeof(eh)) {
+ printf("Can't read elf header\n");
+ return;
}
- return (0);
+ if (!IS_ELF(eh)) {
+ printf("Not an ELF file\n");
+ return;
+ }
+ for (i = 0; i < eh.e_phnum; i++) {
+ fs_off = eh.e_phoff + i * eh.e_phentsize;
+ if (zbread((char *)&ph, fs_off, sizeof(ph)) != sizeof(ph)) {
+ printf("Can't read program header %d\n", i);
+ return;
+ }
+ if (ph.p_type != PT_LOAD)
+ continue;
+ fs_off = ph.p_offset;
+ p = (caddr_t)ph.p_vaddr;
+ if (zbread(p, fs_off, ph.p_filesz) != ph.p_filesz) {
+ printf("Can't read content of section %d\n", i);
+ return;
+ }
+ if (ph.p_filesz != ph.p_memsz)
+ bzero(p + ph.p_filesz, ph.p_memsz - ph.p_filesz);
+ }
+ ofw_close(bootdev);
+ (*(void (*)(int, int, int, int, ofwfp_t))eh.e_entry)(0, 0, 0, 0, ofw);
}
+#else
+
+#include "ufsread.c"
+
+static struct dmadat __dmadat;
+
static void
load(const char *fname)
{
@@ -421,6 +495,26 @@ load(const char *fname)
(*(void (*)(int, int, int, int, ofwfp_t))eh.e_entry)(0, 0, 0, 0, ofw);
}
+#endif /* ZFSBOOT */
+
+static int
+mount(const char *device)
+{
+
+ if ((bootdev = ofw_open(device)) == -1) {
+ printf("mount: can't open device\n");
+ return (-1);
+ }
+#ifndef ZFSBOOT
+ dmadat = &__dmadat;
+ if (fsread(0, NULL, 0)) {
+ printf("mount: can't read superblock\n");
+ return (-1);
+ }
+#endif
+ return (0);
+}
+
static int
dskread(void *buf, u_int64_t lba, int nblk)
{
diff --git a/sys/boot/sparc64/loader/Makefile b/sys/boot/sparc64/loader/Makefile
index d32fbab..27359b2 100644
--- a/sys/boot/sparc64/loader/Makefile
+++ b/sys/boot/sparc64/loader/Makefile
@@ -3,8 +3,8 @@
.include <bsd.own.mk>
MK_SSP= no
-PROG= loader
-NEWVERSWHAT= "bootstrap loader" sparc64
+PROG?= loader
+NEWVERSWHAT?= "bootstrap loader" sparc64
INSTALLFLAGS= -b
# Architecture-specific loader code
@@ -13,12 +13,17 @@ SRCS= locore.S main.c metadata.c vers.c
LOADER_DISK_SUPPORT?= yes
LOADER_UFS_SUPPORT?= yes
LOADER_CD9660_SUPPORT?= yes
+LOADER_ZFS_SUPPORT?= no
LOADER_NET_SUPPORT?= yes
LOADER_NFS_SUPPORT?= yes
LOADER_TFTP_SUPPORT?= yes
LOADER_GZIP_SUPPORT?= yes
LOADER_BZIP2_SUPPORT?= no
+LOADER_DEBUG?= no
+.if ${LOADER_DEBUG} == "yes"
+CFLAGS+= -DLOADER_DEBUG
+.endif
.if ${LOADER_DISK_SUPPORT} == "yes"
CFLAGS+= -DLOADER_DISK_SUPPORT
.endif
@@ -28,6 +33,11 @@ CFLAGS+= -DLOADER_UFS_SUPPORT
.if ${LOADER_CD9660_SUPPORT} == "yes"
CFLAGS+= -DLOADER_CD9660_SUPPORT
.endif
+.if ${LOADER_ZFS_SUPPORT} == "yes"
+CFLAGS+= -DLOADER_ZFS_SUPPORT
+CFLAGS+= -I${.CURDIR}/../../zfs
+CFLAGS+= -I${.CURDIR}/../../../cddl/boot/zfs
+.endif
.if ${LOADER_GZIP_SUPPORT} == "yes"
CFLAGS+= -DLOADER_GZIP_SUPPORT
.endif
@@ -47,7 +57,8 @@ CFLAGS+= -DLOADER_TFTP_SUPPORT
.if ${MK_FORTH} != "no"
# Enable BootForth
BOOT_FORTH= yes
-CFLAGS+= -DBOOT_FORTH -I${.CURDIR}/../../ficl -I${.CURDIR}/../../ficl/sparc64
+CFLAGS+= -DBOOT_FORTH -I${.CURDIR}/../../ficl
+CFLAGS+= -I${.CURDIR}/../../ficl/sparc64
LIBFICL= ${.OBJDIR}/../../ficl/libficl.a
.endif
@@ -75,8 +86,9 @@ CFLAGS+= -I${.CURDIR}/../../../../lib/libstand/
DPADD= ${LIBFICL} ${LIBOFW} ${LIBSTAND}
LDADD= ${LIBFICL} ${LIBOFW} -lstand
-vers.c: ${.CURDIR}/../../common/newvers.sh ${.CURDIR}/version
- sh ${.CURDIR}/../../common/newvers.sh ${.CURDIR}/version ${NEWVERSWHAT}
+vers.c: ${.CURDIR}/../../common/newvers.sh ${.CURDIR}/../loader/version
+ sh ${.CURDIR}/../../common/newvers.sh ${.CURDIR}/../loader/version \
+ ${NEWVERSWHAT}
loader.help: help.common help.sparc64
cat ${.ALLSRC} | \
diff --git a/sys/boot/sparc64/loader/main.c b/sys/boot/sparc64/loader/main.c
index 8eba04a..dbbf08d 100644
--- a/sys/boot/sparc64/loader/main.c
+++ b/sys/boot/sparc64/loader/main.c
@@ -51,6 +51,9 @@ __FBSDID("$FreeBSD$");
#include <sys/linker.h>
#include <sys/queue.h>
#include <sys/types.h>
+#ifdef LOADER_ZFS_SUPPORT
+#include <sys/vtoc.h>
+#endif
#include <vm/vm.h>
#include <machine/asi.h>
@@ -143,6 +146,11 @@ static vm_offset_t heapva;
static phandle_t root;
+#ifdef LOADER_ZFS_SUPPORT
+static int zfs_dev_init(void);
+#include "zfs.c"
+#endif
+
/*
* Machine dependent structures that the machine independent
* loader part uses.
@@ -154,6 +162,9 @@ struct devsw *devsw[] = {
#ifdef LOADER_NET_SUPPORT
&netdev,
#endif
+#ifdef LOADER_ZFS_SUPPORT
+ &zfs_dev,
+#endif
0
};
struct arch_switch archsw;
@@ -166,6 +177,7 @@ struct file_format *file_formats[] = {
&sparc64_elf,
0
};
+
struct fs_ops *file_system[] = {
#ifdef LOADER_UFS_SUPPORT
&ufs_fsops,
@@ -173,6 +185,9 @@ struct fs_ops *file_system[] = {
#ifdef LOADER_CD9660_SUPPORT
&cd9660_fsops,
#endif
+#ifdef LOADER_ZFS_SUPPORT
+ &zfs_fsops,
+#endif
#ifdef LOADER_ZIP_SUPPORT
&zipfs_fsops,
#endif
@@ -721,6 +736,82 @@ tlb_init_sun4u(void)
panic("%s: can't allocate TLB store", __func__);
}
+#ifdef LOADER_ZFS_SUPPORT
+
+static int
+zfs_dev_init(void)
+{
+ struct vtoc8 vtoc;
+ char devname[512];
+ spa_t *spa;
+ vdev_t *vdev;
+ uint64_t guid;
+ int fd, part, unit;
+
+ zfs_init();
+
+ guid = 0;
+ /* Get the GUID of the ZFS pool on the boot device. */
+ fd = open(getenv("currdev"), O_RDONLY);
+ if (fd != -1) {
+ if (vdev_probe(vdev_read, (void *)(uintptr_t) fd, &spa) == 0)
+ guid = spa->spa_guid;
+ close(fd);
+ }
+
+ /* Clean up the environment to let ZFS work. */
+ while ((vdev = STAILQ_FIRST(&zfs_vdevs)) != NULL) {
+ STAILQ_REMOVE_HEAD(&zfs_vdevs, v_alllink);
+ free(vdev);
+ }
+ while ((spa = STAILQ_FIRST(&zfs_pools)) != NULL) {
+ STAILQ_REMOVE_HEAD(&zfs_pools, spa_link);
+ free(spa);
+ }
+
+ for (unit = 0; unit < MAXBDDEV; unit++) {
+ /* Find freebsd-zfs slices in the VTOC. */
+ sprintf(devname, "disk%d:", unit);
+ fd = open(devname, O_RDONLY);
+ if (fd == -1)
+ continue;
+ lseek(fd, 0, SEEK_SET);
+ if (read(fd, &vtoc, sizeof(vtoc)) != sizeof(vtoc)) {
+ close(fd);
+ continue;
+ }
+ close(fd);
+
+ for (part = 0; part < 8; part++) {
+ if (part == 2 || vtoc.part[part].tag !=
+ VTOC_TAG_FREEBSD_ZFS)
+ continue;
+ sprintf(devname, "disk%d:%c", unit, part + 'a');
+ fd = open(devname, O_RDONLY);
+ if (fd == -1)
+ break;
+
+ if (vdev_probe(vdev_read, (void*)(uintptr_t) fd, 0))
+ close(fd);
+ }
+ }
+
+ if (guid != 0) {
+ unit = zfs_guid_to_unit(guid);
+ if (unit >= 0) {
+ /* Update the environment for ZFS. */
+ sprintf(devname, "zfs%d", unit);
+ env_setenv("currdev", EV_VOLATILE, devname,
+ ofw_setcurrdev, env_nounset);
+ env_setenv("loaddev", EV_VOLATILE, devname,
+ env_noset, env_nounset);
+ }
+ }
+ return (0);
+}
+
+#endif /* LOADER_ZFS_SUPPORT */
+
int
main(int (*openfirm)(void *))
{
@@ -756,14 +847,6 @@ main(int (*openfirm)(void *))
mmu_ops->tlb_init();
/*
- * Initialize devices.
- */
- for (dp = devsw; *dp != 0; dp++) {
- if ((*dp)->dv_init != 0)
- (*dp)->dv_init();
- }
-
- /*
* Set up the current device.
*/
OF_getprop(chosen, "bootpath", bootpath, sizeof(bootpath));
@@ -780,7 +863,8 @@ main(int (*openfirm)(void *))
* needs to be altered.
*/
if (bootpath[strlen(bootpath) - 2] == ':' &&
- bootpath[strlen(bootpath) - 1] == 'f') {
+ bootpath[strlen(bootpath) - 1] == 'f' &&
+ strstr(bootpath, "cdrom")) {
bootpath[strlen(bootpath) - 1] = 'a';
printf("Boot path set to %s\n", bootpath);
}
@@ -790,6 +874,13 @@ main(int (*openfirm)(void *))
env_setenv("loaddev", EV_VOLATILE, bootpath,
env_noset, env_nounset);
+ /*
+ * Initialize devices.
+ */
+ for (dp = devsw; *dp != 0; dp++)
+ if ((*dp)->dv_init != 0)
+ (*dp)->dv_init();
+
printf("\n");
printf("%s, Revision %s\n", bootprog_name, bootprog_rev);
printf("(%s, %s)\n", bootprog_maker, bootprog_date);
diff --git a/sys/boot/sparc64/zfsboot/Makefile b/sys/boot/sparc64/zfsboot/Makefile
new file mode 100644
index 0000000..bf30a32
--- /dev/null
+++ b/sys/boot/sparc64/zfsboot/Makefile
@@ -0,0 +1,13 @@
+# $FreeBSD$
+
+.PATH: ${.CURDIR}/../boot1
+
+PROGNAME= zfsboot
+CFLAGS+= -DZFSBOOT
+FILES= zfsboot
+CLEANFILES+= zfsboot
+
+zfsboot: boot1
+ ln -s ${.ALLSRC} ${.TARGET}
+
+.include "${.CURDIR}/../boot1/Makefile"
diff --git a/sys/boot/sparc64/zfsloader/Makefile b/sys/boot/sparc64/zfsloader/Makefile
new file mode 100644
index 0000000..1ed2808
--- /dev/null
+++ b/sys/boot/sparc64/zfsloader/Makefile
@@ -0,0 +1,9 @@
+# $FreeBSD$
+
+.PATH: ${.CURDIR}/../loader
+
+PROG= zfsloader
+NEWVERSWHAT= "ZFS enabled bootstrap loader" sparc64
+LOADER_ZFS_SUPPORT=yes
+
+.include "${.CURDIR}/../loader/Makefile"
diff --git a/sys/boot/zfs/zfs.c b/sys/boot/zfs/zfs.c
index e313fde..97f924f 100644
--- a/sys/boot/zfs/zfs.c
+++ b/sys/boot/zfs/zfs.c
@@ -399,6 +399,7 @@ zfs_guid_to_unit(uint64_t guid)
return (-1);
}
+#if defined(__amd64__) || defined(__i386__)
static int
zfs_dev_init(void)
{
@@ -441,6 +442,7 @@ zfs_dev_init(void)
return (0);
}
+#endif
/*
* Print information about ZFS pools
OpenPOWER on IntegriCloud