diff options
| author | Marius Strobl <marius@FreeBSD.org> | 2012-05-01 17:16:01 +0000 | 
|---|---|---|
| committer | Marius Strobl <marius@FreeBSD.org> | 2012-05-01 17:16:01 +0000 | 
| commit | 2d75b8321fb07286f8ee3860d96bedd2cb705d2a (patch) | |
| tree | 2e64b2d0817ffb401cbbb6e179b69de9a7917c4a | |
| parent | e2a35695f8cd16d72e5a457b80044c5dd402a5d5 (diff) | |
Notes
| -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 3cae23ce2024a..c2d9ef11af1bd 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 fdc87fde92d5f..a76803909082a 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 dec3e092a7c1f..9a97400c8fa93 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 6b9fa30ace4e2..685d414d5b834 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 d32fbabdfca0e..27359b22dd352 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 8eba04ab86ca2..dbbf08dc14662 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 0000000000000..bf30a32d58954 --- /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 0000000000000..1ed280829245e --- /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 e313fdea380b4..97f924f0b9f1a 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 | 
