diff options
-rw-r--r-- | sys/boot/ofw/libofw/devicename.c | 22 | ||||
-rw-r--r-- | sys/boot/sparc64/Makefile | 2 | ||||
-rw-r--r-- | sys/boot/sparc64/boot1/Makefile | 9 | ||||
-rw-r--r-- | sys/boot/sparc64/boot1/boot1.c | 136 | ||||
-rw-r--r-- | sys/boot/sparc64/loader/Makefile | 22 | ||||
-rw-r--r-- | sys/boot/sparc64/loader/main.c | 109 | ||||
-rw-r--r-- | sys/boot/sparc64/zfsboot/Makefile | 13 | ||||
-rw-r--r-- | sys/boot/sparc64/zfsloader/Makefile | 9 | ||||
-rw-r--r-- | sys/boot/zfs/zfs.c | 2 |
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 |