aboutsummaryrefslogtreecommitdiff
path: root/stand
diff options
context:
space:
mode:
Diffstat (limited to 'stand')
-rw-r--r--stand/common/bootstrap.h2
-rw-r--r--stand/common/console.c23
-rw-r--r--stand/common/dev_net.c57
-rw-r--r--stand/common/install.c4
-rw-r--r--stand/defaults/loader.conf2
-rw-r--r--stand/defaults/loader.conf.56
-rw-r--r--stand/efi/libefi/efinet.c2
-rw-r--r--stand/efi/loader/arch/amd64/elf64_freebsd.c8
-rw-r--r--stand/efi/loader/arch/arm/exec.c11
-rw-r--r--stand/efi/loader/arch/arm64/exec.c8
-rw-r--r--stand/efi/loader/arch/i386/elf64_freebsd.c9
-rw-r--r--stand/efi/loader/arch/riscv/exec.c12
-rw-r--r--stand/efi/loader/main.c4
-rw-r--r--stand/fdt/fdt_loader_cmd.c7
-rw-r--r--stand/i386/Makefile2
-rw-r--r--stand/i386/common/bootargs.h2
-rw-r--r--stand/i386/gptboot/Makefile6
-rw-r--r--stand/i386/gptzfsboot/Makefile7
-rw-r--r--stand/i386/gptzfsboot/zfsboot.c (renamed from stand/i386/zfsboot/zfsboot.c)0
-rw-r--r--stand/i386/isoboot/Makefile6
-rw-r--r--stand/i386/libi386/Makefile1
-rw-r--r--stand/i386/libi386/biosmemdisk.c140
-rw-r--r--stand/i386/libi386/libi386.h2
-rw-r--r--stand/i386/loader/main.c5
-rw-r--r--stand/i386/zfsboot/Makefile92
-rw-r--r--stand/i386/zfsboot/Makefile.depend17
-rw-r--r--stand/i386/zfsboot/zfsboot.8130
-rw-r--r--stand/i386/zfsboot/zfsldr.S281
-rw-r--r--stand/libsa/bootp.c78
-rw-r--r--stand/libsa/hexdump.c2
-rw-r--r--stand/libsa/pkgfs.c33
-rw-r--r--stand/libsa/stand.h18
-rw-r--r--stand/libsa/zfs/zfsimpl.c70
33 files changed, 353 insertions, 694 deletions
diff --git a/stand/common/bootstrap.h b/stand/common/bootstrap.h
index dca0cf6bb2d5..17887919089c 100644
--- a/stand/common/bootstrap.h
+++ b/stand/common/bootstrap.h
@@ -372,6 +372,8 @@ extern struct arch_switch archsw;
/* This must be provided by the MD code, but should it be in the archsw? */
void delay(int delay);
+int setprint_delay(struct env_var *ev, int flags, const void *value);
+
/* common code to set currdev variable. */
int gen_setcurrdev(struct env_var *ev, int flags, const void *value);
int mount_currdev(struct env_var *, int, const void *);
diff --git a/stand/common/console.c b/stand/common/console.c
index 82cb552b4ef2..65ab7ffad622 100644
--- a/stand/common/console.c
+++ b/stand/common/console.c
@@ -44,6 +44,8 @@ static int twiddle_set(struct env_var *ev, int flags, const void *value);
#endif
int module_verbose = MODULE_VERBOSE;
+static uint32_t print_delay_usec = 0;
+
static int
module_verbose_set(struct env_var *ev, int flags, const void *value)
{
@@ -66,6 +68,23 @@ module_verbose_set(struct env_var *ev, int flags, const void *value)
}
/*
+ * Hook to set the print delay
+ */
+int
+setprint_delay(struct env_var *ev, int flags, const void *value)
+{
+ char *end;
+ int usec = strtol(value, &end, 10);
+
+ if (*(char *)value == '\0' || *end != '\0')
+ return (EINVAL);
+ if (usec < 0)
+ return (EINVAL);
+ print_delay_usec = usec;
+ return (0);
+}
+
+/*
* Detect possible console(s) to use. If preferred console(s) have been
* specified, mark them as active. Else, mark the first probed console
* as active. Also create the console variable.
@@ -178,6 +197,10 @@ putchar(int c)
(C_PRESENTOUT | C_ACTIVEOUT))
consoles[cons]->c_out(c);
}
+
+ /* Pause after printing newline character if a print delay is set */
+ if (print_delay_usec != 0 && c == '\n')
+ delay(print_delay_usec);
}
/*
diff --git a/stand/common/dev_net.c b/stand/common/dev_net.c
index fc6b43ec7a40..964fa514cac5 100644
--- a/stand/common/dev_net.c
+++ b/stand/common/dev_net.c
@@ -66,10 +66,6 @@
#include "dev_net.h"
#include "bootstrap.h"
-#ifdef NETIF_DEBUG
-int debug = 0;
-#endif
-
static char *netdev_name;
static int netdev_sock = -1;
static int netdev_opens;
@@ -143,11 +139,8 @@ net_open(struct open_file *f, ...)
return (ENXIO);
}
netdev_name = strdup(devname);
-#ifdef NETIF_DEBUG
- if (debug)
- printf("%s: netif_open() succeeded\n",
- __func__);
-#endif
+ DEBUG_PRINTF(1,("%s: netif_open() succeeded %#x\n",
+ __func__, rootip.s_addr));
}
/*
* If network params were not set by netif_open(), try to get
@@ -200,10 +193,7 @@ net_close(struct open_file *f)
{
struct devdesc *dev;
-#ifdef NETIF_DEBUG
- if (debug)
- printf("%s: opens=%d\n", __func__, netdev_opens);
-#endif
+ DEBUG_PRINTF(1,("%s: opens=%d\n", __func__, netdev_opens));
dev = f->f_devdata;
dev->d_opendata = NULL;
@@ -216,10 +206,7 @@ net_cleanup(void)
{
if (netdev_sock >= 0) {
-#ifdef NETIF_DEBUG
- if (debug)
- printf("%s: calling netif_close()\n", __func__);
-#endif
+ DEBUG_PRINTF(1,("%s: calling netif_close()\n", __func__));
rootip.s_addr = 0;
free(netdev_name);
netif_close(netdev_sock);
@@ -271,10 +258,7 @@ net_getparams(int sock)
bootp(sock);
if (myip.s_addr != 0)
goto exit;
-#ifdef NETIF_DEBUG
- if (debug)
- printf("%s: BOOTP failed, trying RARP/RPC...\n", __func__);
-#endif
+ DEBUG_PRINTF(1,("%s: BOOTP failed, trying RARP/RPC...\n", __func__));
#endif
/*
@@ -292,10 +276,7 @@ net_getparams(int sock)
printf("%s: bootparam/whoami RPC failed\n", __func__);
return (EIO);
}
-#ifdef NETIF_DEBUG
- if (debug)
- printf("%s: client name: %s\n", __func__, hostname);
-#endif
+ DEBUG_PRINTF(1,("%s: client name: %s\n", __func__, hostname));
/*
* Ignore the gateway from whoami (unreliable).
@@ -309,16 +290,12 @@ net_getparams(int sock)
}
if (smask) {
netmask = smask;
-#ifdef NETIF_DEBUG
- if (debug)
- printf("%s: subnet mask: %s\n", __func__,
- intoa(netmask));
-#endif
+ DEBUG_PRINTF(1,("%s: subnet mask: %s\n", __func__,
+ intoa(netmask)));
}
-#ifdef NETIF_DEBUG
- if (gateip.s_addr && debug)
- printf("%s: net gateway: %s\n", __func__, inet_ntoa(gateip));
-#endif
+ if (gateip.s_addr)
+ DEBUG_PRINTF(1,("%s: net gateway: %s\n", __func__,
+ inet_ntoa(gateip)));
/* Get the root server and pathname. */
if (bp_getfile(sock, "root", &rootip, rootpath)) {
@@ -329,12 +306,10 @@ exit:
if ((rootaddr = net_parse_rootpath()) != INADDR_NONE)
rootip.s_addr = rootaddr;
-#ifdef NETIF_DEBUG
- if (debug) {
- printf("%s: server addr: %s\n", __func__, inet_ntoa(rootip));
- printf("%s: server path: %s\n", __func__, rootpath);
- }
-#endif
+ DEBUG_PRINTF(1,("%s: proto: %d\n", __func__, netproto));
+ DEBUG_PRINTF(1,("%s: server addr: %s\n", __func__, inet_ntoa(rootip)));
+ DEBUG_PRINTF(1,("%s: server port: %d\n", __func__, rootport));
+ DEBUG_PRINTF(1,("%s: server path: %s\n", __func__, rootpath));
return (0);
}
@@ -410,6 +385,8 @@ net_parse_rootpath(void)
(void)strsep(&ptr, ":");
if (ptr != NULL) {
addr = inet_addr(rootpath);
+ DEBUG_PRINTF(1,("rootpath=%s addr=%#x\n",
+ rootpath, addr));
bcopy(ptr, rootpath, strlen(ptr) + 1);
}
} else {
diff --git a/stand/common/install.c b/stand/common/install.c
index 249eca1648f3..d07c4c6fc620 100644
--- a/stand/common/install.c
+++ b/stand/common/install.c
@@ -137,7 +137,9 @@ read_metatags(int fd)
}
*p++ = '\0';
- if (strcmp(tag, "KERNEL") == 0)
+ if (strncmp(tag, "ENV_", 4) == 0)
+ setenv(&tag[4], val, 1);
+ else if (strcmp(tag, "KERNEL") == 0)
error = setpath(&inst_kernel, val);
else if (strcmp(tag, "MODULES") == 0)
error = setmultipath(&inst_modules, val);
diff --git a/stand/defaults/loader.conf b/stand/defaults/loader.conf
index 1834e3ba3b34..f0843f3e930b 100644
--- a/stand/defaults/loader.conf
+++ b/stand/defaults/loader.conf
@@ -95,6 +95,8 @@ audit_event_type="etc_security_audit_event"
# Default is unset and disabled (no delay).
#autoboot_delay="10" # Delay in seconds before autobooting,
# -1 for no user interrupts, NO to disable
+#print_delay="1000000" # Slow printing of loader messages, useful for
+ # debugging. Given in microseconds.
#password="" # Prevent changes to boot options
#bootlock_password="" # Prevent booting (see check-password.4th(8))
#geom_eli_passphrase_prompt="NO" # Prompt for geli(8) passphrase to mount root
diff --git a/stand/defaults/loader.conf.5 b/stand/defaults/loader.conf.5
index 021f68f2309e..dc1c8f7f44e0 100644
--- a/stand/defaults/loader.conf.5
+++ b/stand/defaults/loader.conf.5
@@ -21,7 +21,7 @@
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
-.Dd June 5, 2025
+.Dd June 12, 2025
.Dt LOADER.CONF 5
.Os
.Sh NAME
@@ -116,6 +116,10 @@ option in this manner,
.Va beastie_disable
must be set to
.Dq Li YES .
+.It Ar print_delay
+Add a delay in microseconds after printing each line.
+Default
+.Dq Li 0 .
.It Ar boot_*
See list in
.Xr loader.efi 8
diff --git a/stand/efi/libefi/efinet.c b/stand/efi/libefi/efinet.c
index 186d816cd323..e872110ef08f 100644
--- a/stand/efi/libefi/efinet.c
+++ b/stand/efi/libefi/efinet.c
@@ -256,6 +256,7 @@ efi_env_net_params(struct iodesc *desc)
rootip.s_addr = rootaddr;
#ifdef EFINET_DEBUG
+ printf("%s: proto=%d\n", __func__, netproto);
printf("%s: ip=%s\n", __func__, inet_ntoa(myip));
printf("%s: mask=%s\n", __func__, intoa(netmask));
printf("%s: gateway=%s\n", __func__, inet_ntoa(gateip));
@@ -427,6 +428,7 @@ efinet_dev_init(void)
dif->dif_private = handles2[i];
}
+ efinet_dev.dv_cleanup = netdev.dv_cleanup;
efinet_dev.dv_open = netdev.dv_open;
efinet_dev.dv_close = netdev.dv_close;
efinet_dev.dv_strategy = netdev.dv_strategy;
diff --git a/stand/efi/loader/arch/amd64/elf64_freebsd.c b/stand/efi/loader/arch/amd64/elf64_freebsd.c
index c4265aca035e..35bd4d6c1419 100644
--- a/stand/efi/loader/arch/amd64/elf64_freebsd.c
+++ b/stand/efi/loader/arch/amd64/elf64_freebsd.c
@@ -209,6 +209,12 @@ elf64_exec(struct preloaded_file *fp)
trampoline, PT4);
printf("Start @ 0x%lx ...\n", ehdr->e_entry);
+ /*
+ * we have to cleanup here because net_cleanup() doesn't work after
+ * we call ExitBootServices
+ */
+ dev_cleanup();
+
efi_time_fini();
err = bi_load(fp->f_args, &modulep, &kernend, true);
if (err != 0) {
@@ -218,8 +224,6 @@ elf64_exec(struct preloaded_file *fp)
return (err);
}
- dev_cleanup();
-
trampoline(trampstack, copy_staging == COPY_STAGING_ENABLE ?
efi_copy_finish : efi_copy_finish_nop, kernend, modulep,
PT4, ehdr->e_entry);
diff --git a/stand/efi/loader/arch/arm/exec.c b/stand/efi/loader/arch/arm/exec.c
index c2a79523c02a..3963b6c0104b 100644
--- a/stand/efi/loader/arch/arm/exec.c
+++ b/stand/efi/loader/arch/arm/exec.c
@@ -74,16 +74,17 @@ __elfN(arm_exec)(struct preloaded_file *fp)
printf("Kernel entry at %p...\n", entry);
printf("Kernel args: %s\n", fp->f_args);
+ /*
+ * we have to cleanup here because net_cleanup() doesn't work after
+ * we call ExitBootServices
+ */
+ dev_cleanup();
+
if ((error = bi_load(fp->f_args, &modulep, &kernend, true)) != 0) {
efi_time_init();
return (error);
}
- /* At this point we've called ExitBootServices, so we can't call
- * printf or any other function that uses Boot Services */
-
- dev_cleanup();
-
(*entry)((void *)modulep);
panic("exec returned");
}
diff --git a/stand/efi/loader/arch/arm64/exec.c b/stand/efi/loader/arch/arm64/exec.c
index 91a0503a976f..89e2ad7521a8 100644
--- a/stand/efi/loader/arch/arm64/exec.c
+++ b/stand/efi/loader/arch/arm64/exec.c
@@ -69,6 +69,12 @@ elf64_exec(struct preloaded_file *fp)
ehdr = (Elf_Ehdr *)&(md->md_data);
entry = efi_translate(ehdr->e_entry);
+ /*
+ * we have to cleanup here because net_cleanup() doesn't work after
+ * we call ExitBootServices
+ */
+ dev_cleanup();
+
efi_time_fini();
err = bi_load(fp->f_args, &modulep, &kernendp, true);
if (err != 0) {
@@ -76,8 +82,6 @@ elf64_exec(struct preloaded_file *fp)
return (err);
}
- dev_cleanup();
-
/* Clean D-cache under kernel area and invalidate whole I-cache */
clean_addr = (vm_offset_t)efi_translate(fp->f_addr);
clean_size = (vm_offset_t)efi_translate(kernendp) - clean_addr;
diff --git a/stand/efi/loader/arch/i386/elf64_freebsd.c b/stand/efi/loader/arch/i386/elf64_freebsd.c
index b02cda2269bc..22cdd685ea9b 100644
--- a/stand/efi/loader/arch/i386/elf64_freebsd.c
+++ b/stand/efi/loader/arch/i386/elf64_freebsd.c
@@ -252,6 +252,13 @@ elf64_exec(struct preloaded_file *fp)
ehdr->e_entry
);
+
+ /*
+ * we have to cleanup here because net_cleanup() doesn't work after
+ * we call ExitBootServices
+ */
+ dev_cleanup();
+
efi_time_fini();
err = bi_load(fp->f_args, &modulep, &kernend, true);
if (err != 0) {
@@ -259,8 +266,6 @@ elf64_exec(struct preloaded_file *fp)
return (err);
}
- dev_cleanup();
-
trampoline(trampstack, type == AllocateMaxAddress ? efi_copy_finish :
efi_copy_finish_nop, kernend, modulep, PT4, gdtr, ehdr->e_entry);
diff --git a/stand/efi/loader/arch/riscv/exec.c b/stand/efi/loader/arch/riscv/exec.c
index 9da61229ef68..a53fbd9442b0 100644
--- a/stand/efi/loader/arch/riscv/exec.c
+++ b/stand/efi/loader/arch/riscv/exec.c
@@ -86,17 +86,17 @@ __elfN(exec)(struct preloaded_file *fp)
printf("Kernel entry at %p...\n", entry);
printf("Kernel args: %s\n", fp->f_args);
+ /*
+ * we have to cleanup here because net_cleanup() doesn't work after
+ * we call ExitBootServices
+ */
+ dev_cleanup();
+
if ((error = bi_load(fp->f_args, &modulep, &kernend, true)) != 0) {
efi_time_init();
return (error);
}
- /*
- * At this point we've called ExitBootServices, so we can't call
- * printf or any other function that uses Boot Services
- */
- dev_cleanup();
-
(*entry)((void *)modulep);
panic("exec returned");
}
diff --git a/stand/efi/loader/main.c b/stand/efi/loader/main.c
index 70cdfb2e9328..436676368447 100644
--- a/stand/efi/loader/main.c
+++ b/stand/efi/loader/main.c
@@ -1241,6 +1241,9 @@ main(int argc, CHAR16 *argv[])
#endif
cons_probe();
+ /* Set print_delay variable to have hooks in place. */
+ env_setenv("print_delay", EV_VOLATILE, "", setprint_delay, env_nounset);
+
/* Set up currdev variable to have hooks in place. */
env_setenv("currdev", EV_VOLATILE, "", gen_setcurrdev, env_nounset);
@@ -1547,6 +1550,7 @@ command_seed_entropy(int argc, char *argv[])
}
COMMAND_SET(poweroff, "poweroff", "power off the system", command_poweroff);
+COMMAND_SET(halt, "halt", "power off the system", command_poweroff);
static int
command_poweroff(int argc __unused, char *argv[] __unused)
diff --git a/stand/fdt/fdt_loader_cmd.c b/stand/fdt/fdt_loader_cmd.c
index 226812a5d2a6..161c2435c410 100644
--- a/stand/fdt/fdt_loader_cmd.c
+++ b/stand/fdt/fdt_loader_cmd.c
@@ -1240,13 +1240,6 @@ fdt_cmd_ls(int argc, char *argv[])
return (CMD_OK);
}
-static __inline int
-isprint(int c)
-{
-
- return (c >= ' ' && c <= 0x7e);
-}
-
static int
fdt_isprint(const void *data, int len, int *count)
{
diff --git a/stand/i386/Makefile b/stand/i386/Makefile
index 768496598575..299e070d8cd5 100644
--- a/stand/i386/Makefile
+++ b/stand/i386/Makefile
@@ -18,7 +18,7 @@ SUBDIR.yes+= loader_simp
# special boot programs, 'self-extracting boot2+loader'
SUBDIR.${MK_LOADER_PXEBOOT}+= pxeldr
-SUBDIR.${MK_LOADER_ZFS}+= zfsboot gptzfsboot
+SUBDIR.${MK_LOADER_ZFS}+= gptzfsboot
.if defined(PXEBOOT_DEFAULT_INTERP)
L=${PXEBOOT_DEFAULT_INTERP}
diff --git a/stand/i386/common/bootargs.h b/stand/i386/common/bootargs.h
index dafcf6a55554..072f7ee505fd 100644
--- a/stand/i386/common/bootargs.h
+++ b/stand/i386/common/bootargs.h
@@ -88,7 +88,7 @@ struct bootargs
/*
* geli_boot_data is embedded in geli_boot_args (passed from gptboot to loader)
- * and in zfs_boot_args (passed from zfsboot and gptzfsboot to loader).
+ * and in zfs_boot_args (passed from gptzfsboot to loader).
*/
struct geli_boot_data
{
diff --git a/stand/i386/gptboot/Makefile b/stand/i386/gptboot/Makefile
index b91875d242f5..a829be6c745d 100644
--- a/stand/i386/gptboot/Makefile
+++ b/stand/i386/gptboot/Makefile
@@ -1,6 +1,6 @@
.include <bsd.init.mk>
-.PATH: ${BOOTSRC}/i386/boot2 ${BOOTSRC}/i386/common ${SASRC}
+.PATH: ${BOOTSRC}/i386/boot2 ${BOOTSRC}/i386/common
FILES= gptboot
MAN= gptboot.8
@@ -53,12 +53,12 @@ gptldr.out: gptldr.o
${LD} ${LD_FLAGS} -e start --defsym ORG=${ORG1} -T ${LDSCRIPT} -o ${.TARGET} gptldr.o
CLEANFILES+= gptboot.bin gptboot.out gptboot.o sio.o drv.o \
- cons.o ${OPENCRYPTO_XTS}
+ cons.o
gptboot.bin: gptboot.out
${OBJCOPY} -S -O binary gptboot.out ${.TARGET}
-gptboot.out: ${BTXCRT} gptboot.o sio.o drv.o cons.o ${OPENCRYPTO_XTS}
+gptboot.out: ${BTXCRT} gptboot.o sio.o drv.o cons.o
${LD} ${LD_FLAGS} --defsym ORG=${ORG2} -T ${LDSCRIPT} -o ${.TARGET} ${.ALLSRC} ${LIBSA32}
.include <bsd.prog.mk>
diff --git a/stand/i386/gptzfsboot/Makefile b/stand/i386/gptzfsboot/Makefile
index 0d9fa8b043df..0b67ff8cdaf4 100644
--- a/stand/i386/gptzfsboot/Makefile
+++ b/stand/i386/gptzfsboot/Makefile
@@ -1,7 +1,7 @@
.include <bsd.init.mk>
.PATH: ${BOOTSRC}/i386/boot2 ${BOOTSRC}/i386/gptboot \
- ${BOOTSRC}/i386/zfsboot ${BOOTSRC}/i386/common \
+ ${BOOTSRC}/i386/common \
${BOOTSRC}/common
FILES= gptzfsboot
@@ -65,7 +65,7 @@ gptldr.out: gptldr.o
${LD} ${LD_FLAGS} -e start --defsym ORG=${ORG1} -T ${LDSCRIPT} -o ${.TARGET} gptldr.o
OBJS= zfsboot.o sio.o cons.o bcache.o devopen.o disk.o part.o zfs_cmd.o misc.o
-CLEANFILES+= gptzfsboot.bin gptzfsboot.out ${OBJS} ${OPENCRYPTO_XTS}
+CLEANFILES+= gptzfsboot.bin gptzfsboot.out ${OBJS}
# i386 standalone support library
LIBI386= ${BOOTOBJ}/i386/libi386/libi386.a
@@ -73,8 +73,7 @@ LIBI386= ${BOOTOBJ}/i386/libi386/libi386.a
gptzfsboot.bin: gptzfsboot.out
${OBJCOPY} -S -O binary gptzfsboot.out ${.TARGET}
-gptzfsboot.out: ${BTXCRT} ${OBJS} \
- ${OPENCRYPTO_XTS}
+gptzfsboot.out: ${BTXCRT} ${OBJS}
${LD} ${LD_FLAGS} --defsym ORG=${ORG2} -T ${LDSCRIPT} -o ${.TARGET} ${.ALLSRC} ${LIBI386} ${LIBSA32}
zfsboot.o: ${ZFSSRC}/zfsimpl.c
diff --git a/stand/i386/zfsboot/zfsboot.c b/stand/i386/gptzfsboot/zfsboot.c
index 4c8eae9b65e5..4c8eae9b65e5 100644
--- a/stand/i386/zfsboot/zfsboot.c
+++ b/stand/i386/gptzfsboot/zfsboot.c
diff --git a/stand/i386/isoboot/Makefile b/stand/i386/isoboot/Makefile
index 7973f8029aa0..0049e7fd3e0a 100644
--- a/stand/i386/isoboot/Makefile
+++ b/stand/i386/isoboot/Makefile
@@ -1,7 +1,7 @@
.include <bsd.init.mk>
.PATH: ${BOOTSRC}/i386/boot2 ${BOOTSRC}/i386/gptboot \
- ${BOOTSRC}/i386/common ${SASRC}
+ ${BOOTSRC}/i386/common
FILES= isoboot
MAN= isoboot.8
@@ -51,12 +51,12 @@ gptldr.out: gptldr.o
${LD} ${LD_FLAGS} -e start --defsym ORG=${ORG1} -T ${LDSCRIPT} -o ${.TARGET} gptldr.o
CLEANFILES+= isoboot.bin isoboot.out isoboot.o sio.o drv.o \
- cons.o ${OPENCRYPTO_XTS}
+ cons.o
isoboot.bin: isoboot.out
${OBJCOPY} -S -O binary isoboot.out ${.TARGET}
-isoboot.out: ${BTXCRT} isoboot.o sio.o drv.o cons.o ${OPENCRYPTO_XTS}
+isoboot.out: ${BTXCRT} isoboot.o sio.o drv.o cons.o
${LD} ${LD_FLAGS} --defsym ORG=${ORG2} -T ${LDSCRIPT} -o ${.TARGET} ${.ALLSRC} ${LIBSA32}
.include <bsd.prog.mk>
diff --git a/stand/i386/libi386/Makefile b/stand/i386/libi386/Makefile
index 038557c6a826..7205d3a61988 100644
--- a/stand/i386/libi386/Makefile
+++ b/stand/i386/libi386/Makefile
@@ -7,6 +7,7 @@ SRCS+= bio.c
SRCS+= biosacpi.c
SRCS+= biosdisk.c
SRCS+= biosmem.c
+SRCS+= biosmemdisk.c
SRCS+= biospci.c
SRCS+= biospnp.c
SRCS+= biossmap.c
diff --git a/stand/i386/libi386/biosmemdisk.c b/stand/i386/libi386/biosmemdisk.c
new file mode 100644
index 000000000000..208ae289950a
--- /dev/null
+++ b/stand/i386/libi386/biosmemdisk.c
@@ -0,0 +1,140 @@
+/*-
+ * Copyright (c) 2020 Richard Russo <russor@ruka.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+/*
+ * Source of information: https://repo.or.cz/syslinux.git
+ *
+ * Implements the MEMDISK protocol from syslinux, found in doc/memdisk.txt
+ * (search MEMDISK info structure). Since we validate the pointer to the mBFT, a
+ * minimum version of 3.85 is needed. Note: All this could be done in the
+ * kernel, since we don't have hooks to use this inside the boot loader. The
+ * details of these structures can be found in memdisk/memdisk.inc (search
+ * for mBFT).
+ *
+ * The kernel could just grab the mBFT table, but instead relies on us finding
+ * it and setting the right env variables.
+ */
+#include <stand.h>
+#include <machine/stdarg.h>
+#include <bootstrap.h>
+#include <btxv86.h>
+#include "libi386.h"
+
+#include "platform/acfreebsd.h"
+#include "acconfig.h"
+#define ACPI_SYSTEM_XFACE
+#include "actypes.h"
+#include "actbl.h"
+
+struct memdisk_info {
+ uint32_t mdi_13h_hook_ptr; /* not included in mdi_length! */
+ uint16_t mdi_length;
+ uint8_t mdi_minor;
+ uint8_t mdi_major;
+ uint32_t mdi_disk_ptr;
+ uint32_t mdi_disk_sectors;
+ uint32_t mdi_far_ptr_cmdline;
+ uint32_t mdi_old_int13h;
+ uint32_t mdi_old_int15h;
+ uint16_t mdi_dos_mem_before;
+ uint8_t mdi_boot_loader_id;
+ uint8_t mdi_sector_size; /* Code below assumes this is last */
+} __attribute__((packed));
+
+struct safe_13h_hook {
+ char sh_jmp[3];
+ char sh_id[8];
+ char sh_vendor[8];
+ uint16_t sh_next_offset;
+ uint16_t sh_next_segment;
+ uint32_t sh_flags;
+ uint32_t sh_mbft;
+} __attribute__((packed));
+
+/*
+ * Maximum length of INT 13 entries we'll chase. Real disks are on this list,
+ * potentially, so we may have to look through them to find the memdisk.
+ */
+#define MEMDISK_MAX 32
+
+/*
+ * Scan for MEMDISK virtual block devices
+ */
+void
+biosmemdisk_detect(void)
+{
+ char line[80], scratch[80];
+ int hook = 0, count = 0, sector_size;
+ uint16_t segment, offset;
+ struct safe_13h_hook *probe;
+ ACPI_TABLE_HEADER *mbft;
+ uint8_t *cp, sum;
+ struct memdisk_info *mdi;
+
+ /*
+ * Walk through the int13 handler linked list, looking for possible
+ * MEMDISKs.
+ *
+ * The max is arbitrary to ensure termination.
+ */
+ offset = *(uint16_t *)PTOV(0x13 * 4);
+ segment = *(uint16_t *)PTOV(0x13 * 4 + 2);
+ while (hook < MEMDISK_MAX && !(segment == 0 && offset == 0)) {
+ /*
+ * Walk the linked list, making sure each node has the right
+ * signature and only looking at MEMDISK nodes.
+ */
+ probe = (struct safe_13h_hook *)PTOV(segment * 16 + offset);
+ if (memcmp(probe->sh_id, "$INT13SF", sizeof(probe->sh_id)) != 0) {
+ printf("Found int 13h unsafe hook at %p (%x:%x)\n",
+ probe, segment, offset);
+ break;
+ }
+ if (memcmp(probe->sh_vendor, "MEMDISK ", sizeof(probe->sh_vendor)) != 0)
+ goto end_of_loop;
+
+ /*
+ * If it is a memdisk, make sure the mBFT signature is correct
+ * and its checksum is right.
+ */
+ mbft = (ACPI_TABLE_HEADER *)PTOV(probe->sh_mbft);
+ if (memcmp(mbft->Signature, "mBFT", sizeof(mbft->Signature)) != 0)
+ goto end_of_loop;
+ sum = 0;
+ cp = (uint8_t *)mbft;
+ for (int idx = 0; idx < mbft->Length; ++idx)
+ sum += *(cp + idx);
+ if (sum != 0)
+ goto end_of_loop;
+
+ /*
+ * The memdisk info follows the ACPI_TABLE_HEADER in the mBFT
+ * section. If the sector size is present and non-zero use it
+ * otherwise assume 512.
+ */
+ mdi = (struct memdisk_info *)PTOV(probe->sh_mbft + sizeof(*mbft));
+ sector_size = 512;
+ if (mdi->mdi_length + sizeof(mdi->mdi_13h_hook_ptr) >= sizeof(*mdi) &&
+ mdi->mdi_sector_size != 0)
+ sector_size = 1 << mdi->mdi_sector_size;
+
+ printf("memdisk %d.%d disk at %#x (%d sectors = %d bytes)\n",
+ mdi->mdi_major, mdi->mdi_minor, mdi->mdi_disk_ptr,
+ mdi->mdi_disk_sectors, mdi->mdi_disk_sectors * sector_size);
+
+ snprintf(line, sizeof(line), "hint.md.%d.physaddr", count);
+ snprintf(scratch, sizeof(scratch), "0x%08x", mdi->mdi_disk_ptr);
+ setenv(line, scratch, 1);
+ snprintf(line, sizeof(line), "hint.md.%d.len", count);
+ snprintf(scratch, sizeof(scratch), "%d", mdi->mdi_disk_sectors * sector_size);
+ setenv(line, scratch, 1);
+ count++;
+end_of_loop:
+ hook++;
+ offset = probe->sh_next_offset;
+ segment = probe->sh_next_segment;
+ }
+}
diff --git a/stand/i386/libi386/libi386.h b/stand/i386/libi386/libi386.h
index d456ef58d7c2..caf565dd0656 100644
--- a/stand/i386/libi386/libi386.h
+++ b/stand/i386/libi386/libi386.h
@@ -149,3 +149,5 @@ int bi_load64(char *args, vm_offset_t *modulep,
vm_offset_t *kernend, int add_smap);
void pxe_enable(void *pxeinfo);
+
+void biosmemdisk_detect(void);
diff --git a/stand/i386/loader/main.c b/stand/i386/loader/main.c
index a7dfb2dde762..a70b3a253b90 100644
--- a/stand/i386/loader/main.c
+++ b/stand/i386/loader/main.c
@@ -198,7 +198,7 @@ main(void)
#ifdef LOADER_ZFS_SUPPORT
/*
- * zfsboot and gptzfsboot have always passed KARGS_FLAGS_ZFS,
+ * gptzfsboot has always passed KARGS_FLAGS_ZFS,
* so if that is set along with KARGS_FLAGS_EXTARG we know we
* can interpret the extarg data as a struct zfs_boot_args.
*/
@@ -251,6 +251,9 @@ main(void)
initial_bootinfo->bi_extmem = bios_extmem / 1024;
}
+ /* detect MEMDISK virtual disks */
+ biosmemdisk_detect();
+
/* detect SMBIOS for future reference */
smbios_detect(NULL);
diff --git a/stand/i386/zfsboot/Makefile b/stand/i386/zfsboot/Makefile
deleted file mode 100644
index b619b84c368e..000000000000
--- a/stand/i386/zfsboot/Makefile
+++ /dev/null
@@ -1,92 +0,0 @@
-.include <bsd.init.mk>
-
-.PATH: ${BOOTSRC}/i386/boot2 ${BOOTSRC}/i386/common ${BOOTSRC}/common
-
-FILES= zfsboot
-MAN= zfsboot.8
-
-BOOT_COMCONSOLE_PORT?= 0x3f8
-BOOT_COMCONSOLE_SPEED?= 115200
-B2SIOFMT?= 0x3
-
-REL1= 0x700
-ORG1= 0x7c00
-ORG2= 0x2000
-
-CFLAGS+=-DBOOTPROG=\"zfsboot\" \
- -O1 \
- -DBOOT2 \
- -DLOADER_GPT_SUPPORT \
- -DLOADER_MBR_SUPPORT \
- -DLOADER_ZFS_SUPPORT \
- -DLOADER_UFS_SUPPORT \
- -DSIOPRT=${BOOT_COMCONSOLE_PORT} \
- -DSIOFMT=${B2SIOFMT} \
- -DSIOSPD=${BOOT_COMCONSOLE_SPEED} \
- -I${LDRSRC} \
- -I${BOOTSRC}/i386/common \
- -I${BOOTSRC}/i386/libi386 \
- -I${ZFSSRC} \
- -I${SYSDIR}/crypto/skein \
- -I${SYSDIR}/cddl/boot/zfs \
- -I${SYSDIR}/contrib/openzfs/include \
- -I${SYSDIR}/contrib/openzfs/include/os/freebsd/spl \
- -I${SYSDIR}/contrib/openzfs/include/os/freebsd/zfs \
- -I${SYSDIR}/cddl/contrib/opensolaris/common/lz4 \
- -I${BOOTSRC}/i386/boot2 \
- -Wall -Waggregate-return -Wbad-function-cast -Wno-cast-align \
- -Wmissing-declarations -Wmissing-prototypes -Wnested-externs \
- -Wpointer-arith -Wshadow -Wstrict-prototypes -Wwrite-strings
-
-CFLAGS.part.c+= -DHAVE_MEMCPY -I${SRCTOP}/sys/contrib/zlib
-
-CFLAGS.gcc+= --param max-inline-insns-single=100
-
-LD_FLAGS+=${LD_FLAGS_BIN}
-
-CLEANFILES+= zfsboot
-
-zfsboot: zfsboot1 zfsboot2
- cat zfsboot1 zfsboot2 > zfsboot
-
-CLEANFILES+= zfsboot1 zfsldr.out zfsldr.o
-
-zfsboot1: zfsldr.out
- ${OBJCOPY} -S -O binary zfsldr.out ${.TARGET}
-
-zfsldr.out: zfsldr.o
- ${LD} ${LD_FLAGS} -e start --defsym ORG=${ORG1} -T ${LDSCRIPT} -o ${.TARGET} zfsldr.o
-
-OBJS= zfsboot.o sio.o cons.o bcache.o devopen.o disk.o part.o zfs_cmd.o misc.o
-CLEANFILES+= zfsboot2 zfsboot.ld zfsboot.ldr zfsboot.bin zfsboot.out \
- ${OBJS}
-
-# We currently allow 256k bytes for zfsboot - in practice it could be
-# any size up to 3.5Mb but keeping it fixed size simplifies zfsldr.
-#
-BOOT2SIZE= 262144
-
-# i386 standalone support library
-LIBI386= ${BOOTOBJ}/i386/libi386/libi386.a
-
-zfsboot2: zfsboot.ld
- @set -- `ls -l ${.ALLSRC}`; x=$$((${BOOT2SIZE}-$$5)); \
- echo "$$x bytes available"; test $$x -ge 0
- ${DD} if=${.ALLSRC} of=${.TARGET} bs=${BOOT2SIZE} conv=sync
-
-zfsboot.ld: zfsboot.ldr zfsboot.bin ${BTXKERN}
- btxld -v -E ${ORG2} -f bin -b ${BTXKERN} -l zfsboot.ldr \
- -o ${.TARGET} -P 1 zfsboot.bin
-
-zfsboot.ldr:
- :> ${.TARGET}
-
-zfsboot.bin: zfsboot.out
- ${OBJCOPY} -S -O binary zfsboot.out ${.TARGET}
-
-zfsboot.out: ${BTXCRT} ${OBJS}
- ${LD} ${LD_FLAGS} --defsym ORG=${ORG2} -T ${LDSCRIPT} -o ${.TARGET} ${.ALLSRC} ${LIBI386} ${LIBSA32}
-
-SRCS= zfsboot.c
-
-.include <bsd.prog.mk>
diff --git a/stand/i386/zfsboot/Makefile.depend b/stand/i386/zfsboot/Makefile.depend
deleted file mode 100644
index 92ab022283fd..000000000000
--- a/stand/i386/zfsboot/Makefile.depend
+++ /dev/null
@@ -1,17 +0,0 @@
-# Autogenerated - do NOT edit!
-
-DIRDEPS = \
- include \
- include/xlocale \
- lib/libmd \
- stand/i386/btx/btx \
- stand/i386/btx/lib \
- stand/libsa32 \
- stand/zfs32 \
-
-
-.include <dirdeps.mk>
-
-.if ${DEP_RELDIR} == ${_DEP_RELDIR}
-# local dependencies - needed for -jN in clean tree
-.endif
diff --git a/stand/i386/zfsboot/zfsboot.8 b/stand/i386/zfsboot/zfsboot.8
deleted file mode 100644
index a8411bc065d0..000000000000
--- a/stand/i386/zfsboot/zfsboot.8
+++ /dev/null
@@ -1,130 +0,0 @@
-.\" Copyright (c) 2014 Andriy Gapon <avg@FreeBSD.org>
-.\" All rights reserved.
-.\"
-.\" Redistribution and use in source and binary forms, with or without
-.\" modification, are permitted provided that the following conditions
-.\" are met:
-.\" 1. Redistributions of source code must retain the above copyright
-.\" notice, this list of conditions and the following disclaimer.
-.\" 2. Redistributions in binary form must reproduce the above copyright
-.\" notice, this list of conditions and the following disclaimer in the
-.\" documentation and/or other materials provided with the distribution.
-.\"
-.\" THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
-.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
-.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-.\" SUCH DAMAGE.
-.\"
-.Dd March 27, 2018
-.Dt ZFSBOOT 8
-.Os
-.Sh NAME
-.Nm zfsboot
-.Nd bootcode for ZFS on BIOS-based computers
-.Sh DESCRIPTION
-.Nm
-is used on BIOS-based computers to boot from a filesystem in
-a ZFS pool.
-.Nm
-is installed in two parts on a disk or a partition used by a ZFS pool.
-The first part, a single-sector starter boot block, is installed
-at the beginning of the disk or partition.
-The second part, a main boot block, is installed at a special offset
-within the disk or partition.
-Both areas are reserved by the ZFS on-disk specification for boot use.
-If
-.Nm
-is installed in a partition, then that partition should be made
-bootable using appropriate configuration and boot blocks described in
-.Xr boot 8 .
-.Sh BOOTING
-The
-.Nm
-boot process is very similar to that of
-.Xr gptzfsboot 8 .
-One significant difference is that
-.Nm
-does not currently support the GPT partitioning scheme.
-Thus only whole disks and MBR partitions, traditionally referred to as
-slices, are probed for ZFS disk labels.
-See the BUGS section in
-.Xr gptzfsboot 8
-for some limitations of the MBR scheme support.
-.Sh USAGE
-.Nm
-supports all the same prompt and configuration file arguments as
-.Xr gptzfsboot 8 .
-.Sh FILES
-.Bl -tag -width /boot/zfsboot -compact
-.It Pa /boot/zfsboot
-boot code binary
-.It Pa /boot.config
-parameters for the boot block
-.Pq optional
-.It Pa /boot/config
-alternative parameters for the boot block
-.Pq optional
-.El
-.Sh EXAMPLES
-.Nm
-is typically installed using
-.Xr dd 1 .
-To install
-.Nm
-on the
-.Pa ada0
-drive:
-.Bd -literal -offset indent
-dd if=/boot/zfsboot of=/dev/ada0 count=1
-dd if=/boot/zfsboot of=/dev/ada0 iseek=1 oseek=1024
-.Ed
-.Pp
-If the drive is currently in use, the GEOM safety will prevent writes
-and must be disabled before running the above commands:
-.Bd -literal -offset indent
-sysctl kern.geom.debugflags=0x10
-.Ed
-.Pp
-.Nm
-can also be installed in an MBR slice:
-.Bd -literal -offset indent
-gpart create -s mbr ada0
-gpart add -t freebsd ada0
-gpart bootcode -b /boot/boot0 ada0
-gpart set -a active -i 1 ada0
-dd if=/dev/zero of=/dev/ada0s1 count=2
-dd if=/boot/zfsboot of=/dev/ada0s1 count=1
-dd if=/boot/zfsboot of=/dev/ada0s1 iseek=1 oseek=1024
-.Ed
-.Pp
-Note that commands to create and populate a pool are not shown
-in the example above.
-.Sh SEE ALSO
-.Xr dd 1 ,
-.Xr boot.config 5 ,
-.Xr boot 8 ,
-.Xr gptzfsboot 8 ,
-.Xr loader 8 ,
-.Xr zpool 8
-.Sh HISTORY
-.Nm
-appeared in FreeBSD 7.3.
-.Sh AUTHORS
-This manual page was written by
-.An Andriy Gapon Aq avg@FreeBSD.org .
-.Sh BUGS
-Installing
-.Nm
-with
-.Xr dd 1
-is a hack.
-ZFS needs a command to properly install
-.Nm
-onto a ZFS-controlled disk or partition.
diff --git a/stand/i386/zfsboot/zfsldr.S b/stand/i386/zfsboot/zfsldr.S
deleted file mode 100644
index cd8289f952fd..000000000000
--- a/stand/i386/zfsboot/zfsldr.S
+++ /dev/null
@@ -1,281 +0,0 @@
-/*
- * Copyright (c) 1998 Robert Nordier
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are freely
- * permitted provided that the above copyright notice and this
- * paragraph and the following disclaimer are duplicated in all
- * such forms.
- *
- * This software is provided "AS IS" and without any express or
- * implied warranties, including, without limitation, the implied
- * warranties of merchantability and fitness for a particular
- * purpose.
- */
-
-/* Memory Locations */
- .set MEM_ARG,0x900 # Arguments
- .set MEM_ORG,0x7c00 # Origin
- .set MEM_BUF,0x8000 # Load area
- .set MEM_BTX,0x9000 # BTX start
- .set MEM_JMP,0x9010 # BTX entry point
- .set MEM_USR,0xa000 # Client start
- .set BDA_BOOT,0x472 # Boot howto flag
-
-/* Partition Constants */
- .set PRT_OFF,0x1be # Partition offset
- .set PRT_NUM,0x4 # Partitions
- .set PRT_BSD,0xa5 # Partition type
-
-/* Misc. Constants */
- .set SIZ_PAG,0x1000 # Page size
- .set SIZ_SEC,0x200 # Sector size
- .set COPY_BLKS,0x8 # Number of blocks
- # to copy for boot2 (<= 15)
- .set COPY_BLK_SZ,0x8000 # Copy in 32k blocks; must be
- # a multiple of 16 bytes
- .set NSECT,(COPY_BLK_SZ / SIZ_SEC * COPY_BLKS)
- .globl start
- .code16
-
-/*
- * Load the rest of zfsboot2 and BTX up, copy the parts to the right locations,
- * and start it all up.
- */
-
-/*
- * Setup the segment registers to flat addressing (segment 0) and setup the
- * stack to end just below the start of our code.
- */
-start: cld # String ops inc
- xor %cx,%cx # Zero
- mov %cx,%es # Address
- mov %cx,%ds # data
- mov %cx,%ss # Set up
- mov $start,%sp # stack
-/*
- * Load the MBR and look for the first FreeBSD slice. We use the fake
- * partition entry below that points to the MBR when we call read.
- * The first pass looks for the first active FreeBSD slice. The
- * second pass looks for the first non-active FreeBSD slice if the
- * first one fails.
- */
- call check_edd # Make sure EDD works
- mov $part4,%si # Dummy partition
- xor %eax,%eax # Read MBR
- movl $MEM_BUF,%ebx # from first
- call read # sector
- mov $0x1,%cx # Two passes
-main.1: mov $MEM_BUF+PRT_OFF,%si # Partition table
- movb $0x1,%dh # Partition
-main.2: cmpb $PRT_BSD,0x4(%si) # Our partition type?
- jne main.3 # No
- jcxz main.5 # If second pass
- testb $0x80,(%si) # Active?
- jnz main.5 # Yes
-main.3: add $0x10,%si # Next entry
- incb %dh # Partition
- cmpb $0x1+PRT_NUM,%dh # In table?
- jb main.2 # Yes
- dec %cx # Do two
- jcxz main.1 # passes
-/*
- * If we get here, we didn't find any FreeBSD slices at all, so print an
- * error message and die.
- */
- mov $msg_part,%si # Message
- jmp error # Error
-
-/*
- * Ok, we have a slice and drive in %dx now, so use that to locate and
- * load boot2. %si references the start of the slice we are looking
- * for, so go ahead and load up the COPY_BLKS*COPY_BLK_SZ/SIZ_SEC sectors
- * starting at sector 1024 (i.e. after the two vdev labels). We don't
- * have do anything fancy here to allow for an extra copy of boot1 and
- * a partition table (compare to this section of the UFS bootstrap) so we
- * just load it all at 0x9000. The first part of boot2 is BTX, which wants
- * to run at 0x9000. The boot2.bin binary starts right after the end of BTX,
- * so we have to figure out where the start of it is and then move the
- * binary to 0xc000. Normally, BTX clients start at MEM_USR, or 0xa000,
- * but when we use btxld to create zfsboot2, we use an entry point of
- * 0x2000. That entry point is relative to MEM_USR; thus boot2.bin
- * starts at 0xc000.
- *
- * The load area and the target area for the client overlap so we have
- * to use a decrementing string move. We also play segment register
- * games with the destination address for the move so that the client
- * can be larger than 16k (which would overflow the zero segment since
- * the client starts at 0xc000).
- */
-main.5: mov %dx,MEM_ARG # Save args
- mov $NSECT,%cx # Sector count
- movl $1024,%eax # Offset to boot2
- mov $MEM_BTX,%ebx # Destination buffer
-main.6: pushal # Save params
- call read # Read disk
- popal # Restore
- incl %eax # Advance to
- add $SIZ_SEC,%ebx # next sector
- loop main.6 # If not last, read another
-
- mov $MEM_BTX,%bx # BTX
- mov 0xa(%bx),%si # Get BTX length and set
- add %bx,%si # %si to start of boot2
- dec %si # Set %ds:%si to point at the
- mov %si,%ax # last byte we want to copy
- shr $4,%ax # from boot2, with %si made as
- add $(COPY_BLKS*COPY_BLK_SZ/16),%ax # small as possible.
- and $0xf,%si #
- mov %ax,%ds #
- mov $(MEM_USR+2*SIZ_PAG)/16,%ax # Set %es:(-1) to point at
- add $(COPY_BLKS*COPY_BLK_SZ/16),%ax # the last byte we
- mov %ax,%es # want to copy boot2 into.
- mov $COPY_BLKS,%bx # Copy COPY_BLKS 32k blocks
-copyloop:
- add $COPY_BLK_SZ,%si # Adjust %ds:%si to point at
- mov %ds,%ax # the end of the next 32k to
- sub $COPY_BLK_SZ/16,%ax # copy from boot2
- mov %ax,%ds
- mov $COPY_BLK_SZ-1,%di # Adjust %es:%di to point at
- mov %es,%ax # the end of the next 32k into
- sub $COPY_BLK_SZ/16,%ax # which we want boot2 copied
- mov %ax,%es
- mov $COPY_BLK_SZ,%cx # Copy 32k
- std
- rep movsb
- dec %bx
- jnz copyloop
- mov %cx,%ds # Reset %ds and %es
- mov %cx,%es
- cld # Back to increment
-
-/*
- * Enable A20 so we can access memory above 1 meg.
- * Use the zero-valued %cx as a timeout for embedded hardware which do not
- * have a keyboard controller.
- */
-seta20: cli # Disable interrupts
-seta20.1: dec %cx # Timeout?
- jz seta20.3 # Yes
- inb $0x64,%al # Get status
- testb $0x2,%al # Busy?
- jnz seta20.1 # Yes
- movb $0xd1,%al # Command: Write
- outb %al,$0x64 # output port
-seta20.2: inb $0x64,%al # Get status
- testb $0x2,%al # Busy?
- jnz seta20.2 # Yes
- movb $0xdf,%al # Enable
- outb %al,$0x60 # A20
-seta20.3: sti # Enable interrupts
-
- jmp start+MEM_JMP-MEM_ORG # Start BTX
-
-
-/*
- * Read a sector from the disk. Sets up an EDD packet on the stack
- * and passes it to read. We assume that the destination address is
- * always segment-aligned.
- *
- * %eax - int - LBA to read in relative to partition start
- * %ebx - ptr - destination address
- * %dl - byte - drive to read from
- * %si - ptr - MBR partition entry
- */
-read: xor %ecx,%ecx # Get
- addl 0x8(%si),%eax # LBA
- adc $0,%ecx
- pushl %ecx # Starting absolute block
- pushl %eax # block number
- shr $4,%ebx # Convert to segment
- push %bx # Address of
- push $0 # transfer buffer
- push $0x1 # Read 1 sector
- push $0x10 # Size of packet
- mov %sp,%si # Packet pointer
- mov $0x42,%ah # BIOS: Extended
- int $0x13 # read
- jc read.1 # If error, fail
- lea 0x10(%si),%sp # Clear stack
- ret # If success, return
-read.1: mov %ah,%al # Format
- mov $read_err,%di # error
- call hex8 # code
- mov $msg_read,%si # Set the error message and
- # fall through to the error
- # routine
-/*
- * Print out the error message pointed to by %ds:(%si) followed
- * by a prompt, wait for a keypress, and then reboot the machine.
- */
-error: callw putstr # Display message
- mov $prompt,%si # Display
- callw putstr # prompt
- xorb %ah,%ah # BIOS: Get
- int $0x16 # keypress
- movw $0x1234, BDA_BOOT # Do a warm boot
- ljmp $0xffff,$0x0 # reboot the machine
-/*
- * Display a null-terminated string using the BIOS output.
- */
-putstr.0: mov $0x7,%bx # Page:attribute
- movb $0xe,%ah # BIOS: Display
- int $0x10 # character
-putstr: lodsb # Get char
- testb %al,%al # End of string?
- jne putstr.0 # No
- ret # To caller
-/*
- * Check to see if the disk supports EDD. zfsboot requires EDD and does not
- * support older C/H/S disk I/O.
- */
-check_edd: cmpb $0x80,%dl # Hard drive?
- jb check_edd.1 # No, fail to boot
- mov $0x55aa,%bx # Magic
- push %dx # Save
- movb $0x41,%ah # BIOS: Check
- int $0x13 # extensions present
- pop %dx # Restore
- jc check_edd.1 # If error, fail
- cmp $0xaa55,%bx # Magic?
- jne check_edd.1 # No, so fail
- testb $0x1,%cl # Packet interface?
- jz check_edd.1 # No, so fail
- ret # EDD ok, keep booting
-check_edd.1: mov $msg_chs,%si # Warn that CHS is
- jmp error # unsupported and fail
-/*
- * AL to hex, saving the result to [EDI].
- */
-hex8: push %ax # Save
- shrb $0x4,%al # Do upper
- call hex8.1 # 4
- pop %ax # Restore
-hex8.1: andb $0xf,%al # Get lower 4
- cmpb $0xa,%al # Convert
- sbbb $0x69,%al # to hex
- das # digit
- orb $0x20,%al # To lower case
- stosb # Save char
- ret # (Recursive)
-
-/* Messages */
-
-msg_chs: .asciz "CHS not supported"
-msg_read: .ascii "Read error: "
-read_err: .asciz "XX"
-msg_part: .asciz "Boot error"
-
-prompt: .asciz "\r\n"
-
- .org PRT_OFF,0x90
-
-/* Partition table */
-
- .fill 0x30,0x1,0x0
-part4: .byte 0x80, 0x00, 0x01, 0x00
- .byte 0xa5, 0xfe, 0xff, 0xff
- .byte 0x00, 0x00, 0x00, 0x00
- .byte 0x50, 0xc3, 0x00, 0x00 # 50000 sectors long, bleh
-
- .word 0xaa55 # Magic number
diff --git a/stand/libsa/bootp.c b/stand/libsa/bootp.c
index d919bb59e843..ac37553c6d34 100644
--- a/stand/libsa/bootp.c
+++ b/stand/libsa/bootp.c
@@ -42,7 +42,6 @@
#include <string.h>
-#define BOOTP_DEBUGxx
#define SUPPORT_DHCP
#define DHCP_ENV_NOVENDOR 1 /* do not parse vendor options */
@@ -130,10 +129,7 @@ bootp(int sock)
} wbuf;
struct bootp *rbootp;
-#ifdef BOOTP_DEBUG
- if (debug)
- printf("bootp: socket=%d\n", sock);
-#endif
+ DEBUG_PRINTF(1, ("bootp: socket=%d\n", sock));
if (!bot)
bot = getsecs();
@@ -141,10 +137,7 @@ bootp(int sock)
printf("bootp: bad socket. %d\n", sock);
return;
}
-#ifdef BOOTP_DEBUG
- if (debug)
- printf("bootp: d=%lx\n", (long)d);
-#endif
+ DEBUG_PRINTF(1, ("bootp: socktodesc=%lx\n", (long)d));
bp = &wbuf.wbootp;
bzero(bp, sizeof(*bp));
@@ -225,31 +218,20 @@ bootp(int sock)
netmask = htonl(IN_CLASSB_NET);
else
netmask = htonl(IN_CLASSC_NET);
-#ifdef BOOTP_DEBUG
- if (debug)
- printf("'native netmask' is %s\n", intoa(netmask));
-#endif
+ DEBUG_PRINTF(1, ("'native netmask' is %s\n", intoa(netmask)));
}
-#ifdef BOOTP_DEBUG
- if (debug)
- printf("mask: %s\n", intoa(netmask));
-#endif
+ DEBUG_PRINTF(1,("rootip: %s\n", inet_ntoa(rootip)));
+ DEBUG_PRINTF(1,("mask: %s\n", intoa(netmask)));
/* We need a gateway if root is on a different net */
if (!SAMENET(myip, rootip, netmask)) {
-#ifdef BOOTP_DEBUG
- if (debug)
- printf("need gateway for root ip\n");
-#endif
+ DEBUG_PRINTF(1,("need gateway for root ip\n"));
}
/* Toss gateway if on a different net */
if (!SAMENET(myip, gateip, netmask)) {
-#ifdef BOOTP_DEBUG
- if (debug)
- printf("gateway ip (%s) bad\n", inet_ntoa(gateip));
-#endif
+ DEBUG_PRINTF(1,("gateway ip (%s) bad\n", inet_ntoa(gateip)));
gateip.s_addr = 0;
}
@@ -264,18 +246,11 @@ bootpsend(struct iodesc *d, void *pkt, size_t len)
{
struct bootp *bp;
-#ifdef BOOTP_DEBUG
- if (debug)
- printf("bootpsend: d=%lx called.\n", (long)d);
-#endif
-
+ DEBUG_PRINTF(1,("bootpsend: d=%lx called.\n", (long)d));
bp = pkt;
bp->bp_secs = htons((u_short)(getsecs() - bot));
-#ifdef BOOTP_DEBUG
- if (debug)
- printf("bootpsend: calling sendudp\n");
-#endif
+ DEBUG_PRINTF(1,("bootpsend: calling sendudp\n"));
return (sendudp(d, pkt, len));
}
@@ -288,34 +263,22 @@ bootprecv(struct iodesc *d, void **pkt, void **payload, time_t tleft,
struct bootp *bp;
void *ptr;
-#ifdef BOOTP_DEBUG
- if (debug)
- printf("bootp_recvoffer: called\n");
-#endif
+ DEBUG_PRINTF(1,("bootp_recvoffer: called\n"));
ptr = NULL;
n = readudp(d, &ptr, (void **)&bp, tleft);
if (n == -1 || n < sizeof(struct bootp) - BOOTP_VENDSIZE)
goto bad;
-#ifdef BOOTP_DEBUG
- if (debug)
- printf("bootprecv: checked. bp = %p, n = %zd\n", bp, n);
-#endif
+ DEBUG_PRINTF(1,("bootprecv: checked. bp = %p, n = %zd\n", bp, n));
+
if (bp->bp_xid != htonl(d->xid)) {
-#ifdef BOOTP_DEBUG
- if (debug) {
- printf("bootprecv: expected xid 0x%lx, got 0x%x\n",
- d->xid, ntohl(bp->bp_xid));
- }
-#endif
+ DEBUG_PRINTF(1,("bootprecv: expected xid 0x%lx, got 0x%x\n",
+ d->xid, ntohl(bp->bp_xid)));
goto bad;
}
-#ifdef BOOTP_DEBUG
- if (debug)
- printf("bootprecv: got one!\n");
-#endif
+ DEBUG_PRINTF(1,("bootprecv: got one!\n"));
/* Suck out vendor info */
if (bcmp(vm_rfc1048, bp->bp_vend, sizeof(vm_rfc1048)) == 0) {
@@ -359,10 +322,7 @@ vend_rfc1048(u_char *cp, u_int len)
u_char tag;
const char *val;
-#ifdef BOOTP_DEBUG
- if (debug)
- printf("vend_rfc1048 bootp info. len=%d\n", len);
-#endif
+ DEBUG_PRINTF(1,("vend_rfc1048 bootp info. len=%d\n", len));
ep = cp + len;
/* Step over magic cookie */
@@ -443,10 +403,8 @@ vend_cmu(u_char *cp)
{
struct cmu_vend *vp;
-#ifdef BOOTP_DEBUG
- if (debug)
- printf("vend_cmu bootp info.\n");
-#endif
+ DEBUG_PRINTF(1,("vend_cmu bootp info.\n"));
+
vp = (struct cmu_vend *)cp;
if (vp->v_smask.s_addr != 0) {
diff --git a/stand/libsa/hexdump.c b/stand/libsa/hexdump.c
index 83fd5e277f1b..cce6e323c2cb 100644
--- a/stand/libsa/hexdump.c
+++ b/stand/libsa/hexdump.c
@@ -61,7 +61,7 @@ hexdump(caddr_t region, size_t len)
for (x = 0; x < 16; x++) {
if ((line + x) < (region + len)) {
c = *(uint8_t *)(line + x);
- if ((c < ' ') || (c > '~')) /* !isprint(c) */
+ if (!isprint(c))
c = '.';
emit("%c", c);
} else {
diff --git a/stand/libsa/pkgfs.c b/stand/libsa/pkgfs.c
index 64ebdf033f14..32d488de5cfb 100644
--- a/stand/libsa/pkgfs.c
+++ b/stand/libsa/pkgfs.c
@@ -31,12 +31,6 @@
#include <string.h>
#include <zlib.h>
-#ifdef PKGFS_DEBUG
-#define DBG(x) printf x
-#else
-#define DBG(x)
-#endif
-
static int pkg_open(const char *, struct open_file *);
static int pkg_close(struct open_file *);
static int pkg_read(struct open_file *, void *, size_t, size_t *);
@@ -172,6 +166,9 @@ pkgfs_init(const char *pkgname, struct fs_ops *proto)
exclusive_file_system = NULL;
+ DEBUG_PRINTF(0, ("%s(%s: '%s') -> %d (error=%d)\n", __func__,
+ proto->fs_name, pkgname, fd, errno));
+
if (fd == -1)
return (errno);
@@ -239,7 +236,7 @@ pkg_open_follow(const char *fn, struct open_file *f, int lnks)
if (strcmp(fn, tf->tf_hdr.ut_name) == 0) {
f->f_fsdata = tf;
tf->tf_fp = 0; /* Reset the file pointer. */
- DBG(("%s: found %s type %c\n", __func__,
+ DEBUG_PRINTF(1, ("%s: found %s type %c\n", __func__,
fn, tf->tf_hdr.ut_typeflag[0]));
if (tf->tf_hdr.ut_typeflag[0] == '2') {
/* we have a symlink
@@ -275,6 +272,7 @@ pkg_close(struct open_file *f)
/*
* Free up the cache if we read all of the file.
*/
+ DEBUG_PRINTF(1, ("%s(%s)\n", __func__, tf->tf_hdr.ut_name));
if (tf->tf_fp == tf->tf_size && tf->tf_cachesz > 0) {
free(tf->tf_cache);
tf->tf_cachesz = 0;
@@ -297,6 +295,8 @@ pkg_read(struct open_file *f, void *buf, size_t size, size_t *res)
return (EBADF);
}
+ DEBUG_PRINTF(4, ("%s(%s,%zd)\n", __func__, tf->tf_hdr.ut_name, size));
+
if (tf->tf_cachesz == 0)
cache_data(tf, 1);
@@ -334,6 +334,8 @@ pkg_read(struct open_file *f, void *buf, size_t size, size_t *res)
tf->tf_fp = fp;
if (res != NULL)
*res = size;
+ DEBUG_PRINTF(4, ("%s(%s) res=%zd\n", __func__, tf->tf_hdr.ut_name,
+ (ssize_t)(tf->tf_size - tf->tf_fp)));
return ((sz == -1) ? errno : 0);
}
@@ -377,7 +379,7 @@ pkg_seek(struct open_file *f, off_t ofs, int whence)
return (tf->tf_fp);
}
}
- DBG(("%s: negative file seek (%jd)\n", __func__,
+ DEBUG_PRINTF(3, ("%s: negative file seek (%jd)\n", __func__,
(intmax_t)delta));
errno = ESPIPE;
return (-1);
@@ -511,26 +513,28 @@ cache_data(struct tarfile *tf, int force)
size_t sz;
if (tf == NULL) {
- DBG(("%s: no file to cache data for?\n", __func__));
+ DEBUG_PRINTF(5, ("%s: no file to cache data for?\n",
+ __func__));
errno = EINVAL;
return (-1);
}
pkg = tf->tf_pkg;
if (pkg == NULL) {
- DBG(("%s: no package associated with file?\n", __func__));
+ DEBUG_PRINTF(5, ("%s: no package associated with file?\n",
+ __func__));
errno = EINVAL;
return (-1);
}
if (tf->tf_cachesz > 0) {
- DBG(("%s: data already cached\n", __func__));
+ DEBUG_PRINTF(5, ("%s: data already cached\n", __func__));
errno = EINVAL;
return (-1);
}
if (tf->tf_ofs != pkg->pkg_ofs) {
- DBG(("%s: caching after force read of file %s?\n",
+ DEBUG_PRINTF(5, ("%s: caching after force read of file %s?\n",
__func__, tf->tf_hdr.ut_name));
errno = EINVAL;
return (-1);
@@ -548,7 +552,8 @@ cache_data(struct tarfile *tf, int force)
tf->tf_cache = malloc(sz);
if (tf->tf_cache == NULL) {
- DBG(("%s: could not allocate %d bytes\n", __func__, (int)sz));
+ DEBUG_PRINTF(5, ("%s: could not allocate %d bytes\n",
+ __func__, (int)sz));
errno = ENOMEM;
return (-1);
}
@@ -732,7 +737,7 @@ new_package(int fd, struct package **pp)
}
/*
- * Done parsing the ZIP header. Spkgt the inflation engine.
+ * Done parsing the ZIP header. Start the inflation engine.
*/
error = inflateInit2(&pkg->pkg_zs, -15);
if (error != Z_OK)
diff --git a/stand/libsa/stand.h b/stand/libsa/stand.h
index e1188fb73a26..0e99d8778fa6 100644
--- a/stand/libsa/stand.h
+++ b/stand/libsa/stand.h
@@ -275,6 +275,11 @@ static __inline int ispunct(int c)
(c >= '[' && c <= '`') || (c >= '{' && c <= '~');
}
+static __inline int isprint(int c)
+{
+ return (c >= ' ') && (c <= '~');
+}
+
static __inline int toupper(int c)
{
return islower(c) ? c - 'a' + 'A' : c;
@@ -558,4 +563,17 @@ void tslog_getbuf(void ** buf, size_t * len);
__END_DECLS
+/* define _DEBUG_LEVEL n or _DEBUG_LEVEL_VAR before include */
+#ifndef DEBUG_PRINTF
+# if defined(_DEBUG_LEVEL) || defined(_DEBUG_LEVEL_VAR)
+# ifndef _DEBUG_LEVEL_VAR
+# define _DEBUG_LEVEL_VAR _debug
+static int _debug = _DEBUG_LEVEL;
+# endif
+# define DEBUG_PRINTF(n, args) if (_DEBUG_LEVEL_VAR >= n) printf args
+# else
+# define DEBUG_PRINTF(n, args)
+# endif
+#endif
+
#endif /* STAND_H */
diff --git a/stand/libsa/zfs/zfsimpl.c b/stand/libsa/zfs/zfsimpl.c
index 41ef5a46f30e..971d71d098d3 100644
--- a/stand/libsa/zfs/zfsimpl.c
+++ b/stand/libsa/zfs/zfsimpl.c
@@ -1106,7 +1106,8 @@ vdev_insert(vdev_t *top_vdev, vdev_t *vdev)
}
static int
-vdev_from_nvlist(spa_t *spa, uint64_t top_guid, const nvlist_t *nvlist)
+vdev_from_nvlist(spa_t *spa, uint64_t top_guid, uint64_t txg,
+ const nvlist_t *nvlist)
{
vdev_t *top_vdev, *vdev;
nvlist_t **kids = NULL;
@@ -1120,6 +1121,7 @@ vdev_from_nvlist(spa_t *spa, uint64_t top_guid, const nvlist_t *nvlist)
return (rc);
top_vdev->v_spa = spa;
top_vdev->v_top = top_vdev;
+ top_vdev->v_txg = txg;
vdev_insert(spa->spa_root_vdev, top_vdev);
}
@@ -1163,7 +1165,7 @@ done:
static int
vdev_init_from_label(spa_t *spa, const nvlist_t *nvlist)
{
- uint64_t pool_guid, top_guid;
+ uint64_t pool_guid, top_guid, txg;
nvlist_t *vdevs;
int rc;
@@ -1171,13 +1173,15 @@ vdev_init_from_label(spa_t *spa, const nvlist_t *nvlist)
NULL, &pool_guid, NULL) ||
nvlist_find(nvlist, ZPOOL_CONFIG_TOP_GUID, DATA_TYPE_UINT64,
NULL, &top_guid, NULL) ||
+ nvlist_find(nvlist, ZPOOL_CONFIG_POOL_TXG, DATA_TYPE_UINT64,
+ NULL, &txg, NULL) != 0 ||
nvlist_find(nvlist, ZPOOL_CONFIG_VDEV_TREE, DATA_TYPE_NVLIST,
NULL, &vdevs, NULL)) {
printf("ZFS: can't find vdev details\n");
return (ENOENT);
}
- rc = vdev_from_nvlist(spa, top_guid, vdevs);
+ rc = vdev_from_nvlist(spa, top_guid, txg, vdevs);
nvlist_destroy(vdevs);
return (rc);
}
@@ -1267,6 +1271,21 @@ vdev_update_from_nvlist(uint64_t top_guid, const nvlist_t *nvlist)
return (rc);
}
+/*
+ * Shall not be called on root vdev, that is not linked into zfs_vdevs.
+ * See comment in vdev_create().
+ */
+static void
+vdev_free(struct vdev *vdev)
+{
+ struct vdev *kid, *safe;
+
+ STAILQ_FOREACH_SAFE(kid, &vdev->v_children, v_childlink, safe)
+ vdev_free(kid);
+ STAILQ_REMOVE(&zfs_vdevs, vdev, vdev, v_alllink);
+ free(vdev);
+}
+
static int
vdev_init_from_nvlist(spa_t *spa, const nvlist_t *nvlist)
{
@@ -1313,9 +1332,10 @@ vdev_init_from_nvlist(spa_t *spa, const nvlist_t *nvlist)
vdev = vdev_find(guid);
/*
* Top level vdev is missing, create it.
+ * XXXGL: how can this happen?
*/
if (vdev == NULL)
- rc = vdev_from_nvlist(spa, guid, kids[i]);
+ rc = vdev_from_nvlist(spa, guid, 0, kids[i]);
else
rc = vdev_update_from_nvlist(guid, kids[i]);
if (rc != 0)
@@ -1379,7 +1399,7 @@ spa_create(uint64_t guid, const char *name)
free(spa);
return (NULL);
}
- spa->spa_root_vdev->v_name = strdup("root");
+ spa->spa_root_vdev->v_name = spa->spa_name;
STAILQ_INSERT_TAIL(&zfs_pools, spa, spa_link);
return (spa);
@@ -2006,8 +2026,7 @@ vdev_probe(vdev_phys_read_t *_read, vdev_phys_write_t *_write, void *priv,
vdev_t *vdev;
nvlist_t *nvl;
uint64_t val;
- uint64_t guid, vdev_children;
- uint64_t pool_txg, pool_guid;
+ uint64_t guid, pool_guid, top_guid, txg;
const char *pool_name;
int rc, namelen;
@@ -2063,11 +2082,15 @@ vdev_probe(vdev_phys_read_t *_read, vdev_phys_write_t *_write, void *priv,
}
if (nvlist_find(nvl, ZPOOL_CONFIG_POOL_TXG, DATA_TYPE_UINT64,
- NULL, &pool_txg, NULL) != 0 ||
+ NULL, &txg, NULL) != 0 ||
+ nvlist_find(nvl, ZPOOL_CONFIG_TOP_GUID, DATA_TYPE_UINT64,
+ NULL, &top_guid, NULL) != 0 ||
nvlist_find(nvl, ZPOOL_CONFIG_POOL_GUID, DATA_TYPE_UINT64,
NULL, &pool_guid, NULL) != 0 ||
nvlist_find(nvl, ZPOOL_CONFIG_POOL_NAME, DATA_TYPE_STRING,
- NULL, &pool_name, &namelen) != 0) {
+ NULL, &pool_name, &namelen) != 0 ||
+ nvlist_find(nvl, ZPOOL_CONFIG_GUID, DATA_TYPE_UINT64,
+ NULL, &guid, NULL) != 0) {
/*
* Cache and spare devices end up here - just ignore
* them.
@@ -2083,8 +2106,6 @@ vdev_probe(vdev_phys_read_t *_read, vdev_phys_write_t *_write, void *priv,
if (spa == NULL) {
char *name;
- nvlist_find(nvl, ZPOOL_CONFIG_VDEV_CHILDREN,
- DATA_TYPE_UINT64, NULL, &vdev_children, NULL);
name = malloc(namelen + 1);
if (name == NULL) {
nvlist_destroy(nvl);
@@ -2098,10 +2119,22 @@ vdev_probe(vdev_phys_read_t *_read, vdev_phys_write_t *_write, void *priv,
nvlist_destroy(nvl);
return (ENOMEM);
}
- spa->spa_root_vdev->v_nchildren = vdev_children;
+ } else {
+ struct vdev *kid;
+
+ STAILQ_FOREACH(kid, &spa->spa_root_vdev->v_children,
+ v_childlink)
+ if (kid->v_guid == top_guid && kid->v_txg < txg) {
+ printf("ZFS: pool %s vdev %s ignoring stale "
+ "label from txg 0x%jx, using 0x%jx@0x%jx\n",
+ spa->spa_name, kid->v_name,
+ kid->v_txg, guid, txg);
+ STAILQ_REMOVE(&spa->spa_root_vdev->v_children,
+ kid, vdev, v_childlink);
+ vdev_free(kid);
+ break;
+ }
}
- if (pool_txg > spa->spa_txg)
- spa->spa_txg = pool_txg;
/*
* Get the vdev tree and create our in-core copy of it.
@@ -2109,11 +2142,6 @@ vdev_probe(vdev_phys_read_t *_read, vdev_phys_write_t *_write, void *priv,
* be some kind of alias (overlapping slices, dangerously dedicated
* disks etc).
*/
- if (nvlist_find(nvl, ZPOOL_CONFIG_GUID, DATA_TYPE_UINT64,
- NULL, &guid, NULL) != 0) {
- nvlist_destroy(nvl);
- return (EIO);
- }
vdev = vdev_find(guid);
/* Has this vdev already been inited? */
if (vdev && vdev->v_phys_read) {
@@ -3541,8 +3569,10 @@ zfs_spa_init(spa_t *spa)
return (EIO);
}
rc = load_nvlist(spa, config_object, &nvlist);
- if (rc != 0)
+ if (rc != 0) {
+ printf("ZFS: failed to load pool %s nvlist\n", spa->spa_name);
return (rc);
+ }
rc = zap_lookup(spa, &dir, DMU_POOL_ZPOOL_CHECKPOINT,
sizeof(uint64_t), sizeof(checkpoint) / sizeof(uint64_t),