zfsboot.c revision 213136
1/*-
2 * Copyright (c) 1998 Robert Nordier
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms are freely
6 * permitted provided that the above copyright notice and this
7 * paragraph and the following disclaimer are duplicated in all
8 * such forms.
9 *
10 * This software is provided "AS IS" and without any express or
11 * implied warranties, including, without limitation, the implied
12 * warranties of merchantability and fitness for a particular
13 * purpose.
14 */
15
16#include <sys/cdefs.h>
17__FBSDID("$FreeBSD: head/sys/boot/i386/zfsboot/zfsboot.c 213136 2010-09-24 19:49:12Z pjd $");
18
19#include <sys/param.h>
20#include <sys/errno.h>
21#include <sys/diskmbr.h>
22#ifdef GPT
23#include <sys/gpt.h>
24#endif
25#include <sys/reboot.h>
26#include <sys/queue.h>
27
28#include <machine/bootinfo.h>
29#include <machine/elf.h>
30#include <machine/pc/bios.h>
31
32#include <stdarg.h>
33#include <stddef.h>
34
35#include <a.out.h>
36
37#include <btxv86.h>
38
39#include "lib.h"
40#include "rbx.h"
41#include "drv.h"
42#include "util.h"
43#include "cons.h"
44
45/* Hint to loader that we came from ZFS */
46#define	KARGS_FLAGS_ZFS		0x4
47
48#define PATH_CONFIG	"/boot.config"
49#define PATH_BOOT3	"/boot/zfsloader"
50#define PATH_KERNEL	"/boot/kernel/kernel"
51
52#define ARGS		0x900
53#define NOPT		14
54#define NDEV		3
55
56#define BIOS_NUMDRIVES	0x475
57#define DRV_HARD	0x80
58#define DRV_MASK	0x7f
59
60#define TYPE_AD		0
61#define TYPE_DA		1
62#define TYPE_MAXHARD	TYPE_DA
63#define TYPE_FD		2
64
65#define	MAXBDDEV	31
66
67extern uint32_t _end;
68
69#ifdef GPT
70static const uuid_t freebsd_zfs_uuid = GPT_ENT_TYPE_FREEBSD_ZFS;
71#endif
72static const char optstr[NOPT] = "DhaCcdgmnpqrsv"; /* Also 'P', 'S' */
73static const unsigned char flags[NOPT] = {
74    RBX_DUAL,
75    RBX_SERIAL,
76    RBX_ASKNAME,
77    RBX_CDROM,
78    RBX_CONFIG,
79    RBX_KDB,
80    RBX_GDB,
81    RBX_MUTE,
82    RBX_NOINTR,
83    RBX_PAUSE,
84    RBX_QUIET,
85    RBX_DFLTROOT,
86    RBX_SINGLE,
87    RBX_VERBOSE
88};
89uint32_t opts;
90
91static const char *const dev_nm[NDEV] = {"ad", "da", "fd"};
92static const unsigned char dev_maj[NDEV] = {30, 4, 2};
93
94static char cmd[512];
95static char kname[1024];
96static int comspeed = SIOSPD;
97static struct bootinfo bootinfo;
98static uint32_t bootdev;
99
100vm_offset_t	high_heap_base;
101uint32_t	bios_basemem, bios_extmem, high_heap_size;
102
103static struct bios_smap smap;
104
105/*
106 * The minimum amount of memory to reserve in bios_extmem for the heap.
107 */
108#define	HEAP_MIN	(3 * 1024 * 1024)
109
110static char *heap_next;
111static char *heap_end;
112
113/* Buffers that must not span a 64k boundary. */
114#define READ_BUF_SIZE	8192
115struct dmadat {
116	char rdbuf[READ_BUF_SIZE];	/* for reading large things */
117	char secbuf[READ_BUF_SIZE];	/* for MBR/disklabel */
118};
119static struct dmadat *dmadat;
120
121void exit(int);
122static void load(void);
123static int parse(void);
124static void bios_getmem(void);
125
126static void *
127malloc(size_t n)
128{
129	char *p = heap_next;
130	if (p + n > heap_end) {
131		printf("malloc failure\n");
132		for (;;)
133		    ;
134		return 0;
135	}
136	heap_next += n;
137	return p;
138}
139
140static char *
141strdup(const char *s)
142{
143	char *p = malloc(strlen(s) + 1);
144	strcpy(p, s);
145	return p;
146}
147
148#include "zfsimpl.c"
149
150/*
151 * Read from a dnode (which must be from a ZPL filesystem).
152 */
153static int
154zfs_read(spa_t *spa, const dnode_phys_t *dnode, off_t *offp, void *start, size_t size)
155{
156	const znode_phys_t *zp = (const znode_phys_t *) dnode->dn_bonus;
157	size_t n;
158	int rc;
159
160	n = size;
161	if (*offp + n > zp->zp_size)
162		n = zp->zp_size - *offp;
163
164	rc = dnode_read(spa, dnode, *offp, start, n);
165	if (rc)
166		return (-1);
167	*offp += n;
168
169	return (n);
170}
171
172/*
173 * Current ZFS pool
174 */
175spa_t *spa;
176
177/*
178 * A wrapper for dskread that doesn't have to worry about whether the
179 * buffer pointer crosses a 64k boundary.
180 */
181static int
182vdev_read(vdev_t *vdev, void *priv, off_t off, void *buf, size_t bytes)
183{
184	char *p;
185	daddr_t lba;
186	unsigned int nb;
187	struct dsk *dsk = (struct dsk *) priv;
188
189	if ((off & (DEV_BSIZE - 1)) || (bytes & (DEV_BSIZE - 1)))
190		return -1;
191
192	p = buf;
193	lba = off / DEV_BSIZE;
194	lba += dsk->start;
195	while (bytes > 0) {
196		nb = bytes / DEV_BSIZE;
197		if (nb > READ_BUF_SIZE / DEV_BSIZE)
198			nb = READ_BUF_SIZE / DEV_BSIZE;
199		if (drvread(dsk, dmadat->rdbuf, lba, nb))
200			return -1;
201		memcpy(p, dmadat->rdbuf, nb * DEV_BSIZE);
202		p += nb * DEV_BSIZE;
203		lba += nb;
204		bytes -= nb * DEV_BSIZE;
205	}
206
207	return 0;
208}
209
210static int
211xfsread(const dnode_phys_t *dnode, off_t *offp, void *buf, size_t nbyte)
212{
213    if ((size_t)zfs_read(spa, dnode, offp, buf, nbyte) != nbyte) {
214	printf("Invalid %s\n", "format");
215	return -1;
216    }
217    return 0;
218}
219
220static void
221bios_getmem(void)
222{
223    uint64_t size;
224
225    /* Parse system memory map */
226    v86.ebx = 0;
227    do {
228	v86.ctl = V86_FLAGS;
229	v86.addr = 0x15;		/* int 0x15 function 0xe820*/
230	v86.eax = 0xe820;
231	v86.ecx = sizeof(struct bios_smap);
232	v86.edx = SMAP_SIG;
233	v86.es = VTOPSEG(&smap);
234	v86.edi = VTOPOFF(&smap);
235	v86int();
236	if ((v86.efl & 1) || (v86.eax != SMAP_SIG))
237	    break;
238	/* look for a low-memory segment that's large enough */
239	if ((smap.type == SMAP_TYPE_MEMORY) && (smap.base == 0) &&
240	    (smap.length >= (512 * 1024)))
241	    bios_basemem = smap.length;
242	/* look for the first segment in 'extended' memory */
243	if ((smap.type == SMAP_TYPE_MEMORY) && (smap.base == 0x100000)) {
244	    bios_extmem = smap.length;
245	}
246
247	/*
248	 * Look for the largest segment in 'extended' memory beyond
249	 * 1MB but below 4GB.
250	 */
251	if ((smap.type == SMAP_TYPE_MEMORY) && (smap.base > 0x100000) &&
252	    (smap.base < 0x100000000ull)) {
253	    size = smap.length;
254
255	    /*
256	     * If this segment crosses the 4GB boundary, truncate it.
257	     */
258	    if (smap.base + size > 0x100000000ull)
259		size = 0x100000000ull - smap.base;
260
261	    if (size > high_heap_size) {
262		high_heap_size = size;
263		high_heap_base = smap.base;
264	    }
265	}
266    } while (v86.ebx != 0);
267
268    /* Fall back to the old compatibility function for base memory */
269    if (bios_basemem == 0) {
270	v86.ctl = 0;
271	v86.addr = 0x12;		/* int 0x12 */
272	v86int();
273
274	bios_basemem = (v86.eax & 0xffff) * 1024;
275    }
276
277    /* Fall back through several compatibility functions for extended memory */
278    if (bios_extmem == 0) {
279	v86.ctl = V86_FLAGS;
280	v86.addr = 0x15;		/* int 0x15 function 0xe801*/
281	v86.eax = 0xe801;
282	v86int();
283	if (!(v86.efl & 1)) {
284	    bios_extmem = ((v86.ecx & 0xffff) + ((v86.edx & 0xffff) * 64)) * 1024;
285	}
286    }
287    if (bios_extmem == 0) {
288	v86.ctl = 0;
289	v86.addr = 0x15;		/* int 0x15 function 0x88*/
290	v86.eax = 0x8800;
291	v86int();
292	bios_extmem = (v86.eax & 0xffff) * 1024;
293    }
294
295    /*
296     * If we have extended memory and did not find a suitable heap
297     * region in the SMAP, use the last 3MB of 'extended' memory as a
298     * high heap candidate.
299     */
300    if (bios_extmem >= HEAP_MIN && high_heap_size < HEAP_MIN) {
301	high_heap_size = HEAP_MIN;
302	high_heap_base = bios_extmem + 0x100000 - HEAP_MIN;
303    }
304}
305
306/*
307 * Try to detect a device supported by the legacy int13 BIOS
308 */
309static int
310int13probe(int drive)
311{
312    v86.ctl = V86_FLAGS;
313    v86.addr = 0x13;
314    v86.eax = 0x800;
315    v86.edx = drive;
316    v86int();
317
318    if (!(v86.efl & 0x1) &&				/* carry clear */
319	((v86.edx & 0xff) != (drive & DRV_MASK))) {	/* unit # OK */
320	if ((v86.ecx & 0x3f) == 0) {			/* absurd sector size */
321		return(0);				/* skip device */
322	}
323	return (1);
324    }
325    return(0);
326}
327
328/*
329 * We call this when we find a ZFS vdev - ZFS consumes the dsk
330 * structure so we must make a new one.
331 */
332static struct dsk *
333copy_dsk(struct dsk *dsk)
334{
335    struct dsk *newdsk;
336
337    newdsk = malloc(sizeof(struct dsk));
338    *newdsk = *dsk;
339    return (newdsk);
340}
341
342static void
343probe_drive(struct dsk *dsk, spa_t **spap)
344{
345#ifdef GPT
346    struct gpt_hdr hdr;
347    struct gpt_ent *ent;
348    daddr_t slba, elba;
349    unsigned part, entries_per_sec;
350#endif
351    struct dos_partition *dp;
352    char *sec;
353    unsigned i;
354
355    /*
356     * If we find a vdev on the whole disk, stop here. Otherwise dig
357     * out the MBR and probe each slice in turn for a vdev.
358     */
359    if (vdev_probe(vdev_read, dsk, spap) == 0)
360	return;
361
362    sec = dmadat->secbuf;
363    dsk->start = 0;
364
365#ifdef GPT
366    /*
367     * First check for GPT.
368     */
369    if (drvread(dsk, sec, 1, 1)) {
370	return;
371    }
372    memcpy(&hdr, sec, sizeof(hdr));
373    if (memcmp(hdr.hdr_sig, GPT_HDR_SIG, sizeof(hdr.hdr_sig)) != 0 ||
374	hdr.hdr_lba_self != 1 || hdr.hdr_revision < 0x00010000 ||
375	hdr.hdr_entsz < sizeof(*ent) || DEV_BSIZE % hdr.hdr_entsz != 0) {
376	goto trymbr;
377    }
378
379    /*
380     * Probe all GPT partitions for the presense of ZFS pools. We
381     * return the spa_t for the first we find (if requested). This
382     * will have the effect of booting from the first pool on the
383     * disk.
384     */
385    entries_per_sec = DEV_BSIZE / hdr.hdr_entsz;
386    slba = hdr.hdr_lba_table;
387    elba = slba + hdr.hdr_entries / entries_per_sec;
388    while (slba < elba) {
389	dsk->start = 0;
390	if (drvread(dsk, sec, slba, 1))
391	    return;
392	for (part = 0; part < entries_per_sec; part++) {
393	    ent = (struct gpt_ent *)(sec + part * hdr.hdr_entsz);
394	    if (memcmp(&ent->ent_type, &freebsd_zfs_uuid,
395		     sizeof(uuid_t)) == 0) {
396		dsk->start = ent->ent_lba_start;
397		if (vdev_probe(vdev_read, dsk, spap) == 0) {
398		    /*
399		     * We record the first pool we find (we will try
400		     * to boot from that one).
401		     */
402		    spap = NULL;
403
404		    /*
405		     * This slice had a vdev. We need a new dsk
406		     * structure now since the vdev now owns this one.
407		     */
408		    dsk = copy_dsk(dsk);
409		}
410	    }
411	}
412	slba++;
413    }
414    return;
415trymbr:
416#endif
417
418    if (drvread(dsk, sec, DOSBBSECTOR, 1))
419	return;
420    dp = (void *)(sec + DOSPARTOFF);
421
422    for (i = 0; i < NDOSPART; i++) {
423	if (!dp[i].dp_typ)
424	    continue;
425	dsk->start = dp[i].dp_start;
426	if (vdev_probe(vdev_read, dsk, spap) == 0) {
427	    /*
428	     * We record the first pool we find (we will try to boot
429	     * from that one.
430	     */
431	    spap = 0;
432
433	    /*
434	     * This slice had a vdev. We need a new dsk structure now
435	     * since the vdev now owns this one.
436	     */
437	    dsk = copy_dsk(dsk);
438	}
439    }
440}
441
442int
443main(void)
444{
445    int autoboot, i;
446    dnode_phys_t dn;
447    off_t off;
448    struct dsk *dsk;
449
450    dmadat = (void *)(roundup2(__base + (int32_t)&_end, 0x10000) - __base);
451
452    bios_getmem();
453
454    if (high_heap_size > 0) {
455	heap_end = PTOV(high_heap_base + high_heap_size);
456	heap_next = PTOV(high_heap_base);
457    } else {
458	heap_next = (char *) dmadat + sizeof(*dmadat);
459	heap_end = (char *) PTOV(bios_basemem);
460    }
461
462    dsk = malloc(sizeof(struct dsk));
463    dsk->drive = *(uint8_t *)PTOV(ARGS);
464    dsk->type = dsk->drive & DRV_HARD ? TYPE_AD : TYPE_FD;
465    dsk->unit = dsk->drive & DRV_MASK;
466    dsk->slice = *(uint8_t *)PTOV(ARGS + 1) + 1;
467    dsk->part = 0;
468    dsk->start = 0;
469    dsk->init = 0;
470
471    bootinfo.bi_version = BOOTINFO_VERSION;
472    bootinfo.bi_size = sizeof(bootinfo);
473    bootinfo.bi_basemem = bios_basemem / 1024;
474    bootinfo.bi_extmem = bios_extmem / 1024;
475    bootinfo.bi_memsizes_valid++;
476    bootinfo.bi_bios_dev = dsk->drive;
477
478    bootdev = MAKEBOOTDEV(dev_maj[dsk->type],
479			  dsk->slice, dsk->unit, dsk->part),
480
481    /* Process configuration file */
482
483    autoboot = 1;
484
485    zfs_init();
486
487    /*
488     * Probe the boot drive first - we will try to boot from whatever
489     * pool we find on that drive.
490     */
491    probe_drive(dsk, &spa);
492
493    /*
494     * Probe the rest of the drives that the bios knows about. This
495     * will find any other available pools and it may fill in missing
496     * vdevs for the boot pool.
497     */
498#ifndef VIRTUALBOX
499    for (i = 0; i < *(unsigned char *)PTOV(BIOS_NUMDRIVES); i++)
500#else
501    for (i = 0; i < MAXBDDEV; i++)
502#endif
503    {
504	if ((i | DRV_HARD) == *(uint8_t *)PTOV(ARGS))
505	    continue;
506
507	if (!int13probe(i | DRV_HARD))
508	    break;
509
510	dsk = malloc(sizeof(struct dsk));
511	dsk->drive = i | DRV_HARD;
512	dsk->type = dsk->drive & TYPE_AD;
513	dsk->unit = i;
514	dsk->slice = 0;
515	dsk->part = 0;
516	dsk->start = 0;
517	dsk->init = 0;
518	probe_drive(dsk, NULL);
519    }
520
521    /*
522     * If we didn't find a pool on the boot drive, default to the
523     * first pool we found, if any.
524     */
525    if (!spa) {
526	spa = STAILQ_FIRST(&zfs_pools);
527	if (!spa) {
528	    printf("%s: No ZFS pools located, can't boot\n", BOOTPROG);
529	    for (;;)
530		;
531	}
532    }
533
534    zfs_mount_pool(spa);
535
536    if (zfs_lookup(spa, PATH_CONFIG, &dn) == 0) {
537	off = 0;
538	zfs_read(spa, &dn, &off, cmd, sizeof(cmd));
539    }
540
541    if (*cmd) {
542	if (parse())
543	    autoboot = 0;
544	if (!OPT_CHECK(RBX_QUIET))
545	    printf("%s: %s", PATH_CONFIG, cmd);
546	/* Do not process this command twice */
547	*cmd = 0;
548    }
549
550    /*
551     * Try to exec stage 3 boot loader. If interrupted by a keypress,
552     * or in case of failure, try to load a kernel directly instead.
553     */
554
555    if (autoboot && !*kname) {
556	memcpy(kname, PATH_BOOT3, sizeof(PATH_BOOT3));
557	if (!keyhit(3)) {
558	    load();
559	    memcpy(kname, PATH_KERNEL, sizeof(PATH_KERNEL));
560	}
561    }
562
563    /* Present the user with the boot2 prompt. */
564
565    for (;;) {
566	if (!autoboot || !OPT_CHECK(RBX_QUIET))
567	    printf("\nFreeBSD/x86 boot\n"
568		   "Default: %s:%s\n"
569		   "boot: ",
570		   spa->spa_name, kname);
571	if (ioctrl & IO_SERIAL)
572	    sio_flush();
573	if (!autoboot || keyhit(5))
574	    getstr(cmd, sizeof(cmd));
575	else if (!autoboot || !OPT_CHECK(RBX_QUIET))
576	    putchar('\n');
577	autoboot = 0;
578	if (parse())
579	    putchar('\a');
580	else
581	    load();
582    }
583}
584
585/* XXX - Needed for btxld to link the boot2 binary; do not remove. */
586void
587exit(int x)
588{
589}
590
591static void
592load(void)
593{
594    union {
595	struct exec ex;
596	Elf32_Ehdr eh;
597    } hdr;
598    static Elf32_Phdr ep[2];
599    static Elf32_Shdr es[2];
600    caddr_t p;
601    dnode_phys_t dn;
602    off_t off;
603    uint32_t addr, x;
604    int fmt, i, j;
605
606    if (zfs_lookup(spa, kname, &dn)) {
607	return;
608    }
609    off = 0;
610    if (xfsread(&dn, &off, &hdr, sizeof(hdr)))
611	return;
612    if (N_GETMAGIC(hdr.ex) == ZMAGIC)
613	fmt = 0;
614    else if (IS_ELF(hdr.eh))
615	fmt = 1;
616    else {
617	printf("Invalid %s\n", "format");
618	return;
619    }
620    if (fmt == 0) {
621	addr = hdr.ex.a_entry & 0xffffff;
622	p = PTOV(addr);
623	off = PAGE_SIZE;
624	if (xfsread(&dn, &off, p, hdr.ex.a_text))
625	    return;
626	p += roundup2(hdr.ex.a_text, PAGE_SIZE);
627	if (xfsread(&dn, &off, p, hdr.ex.a_data))
628	    return;
629	p += hdr.ex.a_data + roundup2(hdr.ex.a_bss, PAGE_SIZE);
630	bootinfo.bi_symtab = VTOP(p);
631	memcpy(p, &hdr.ex.a_syms, sizeof(hdr.ex.a_syms));
632	p += sizeof(hdr.ex.a_syms);
633	if (hdr.ex.a_syms) {
634	    if (xfsread(&dn, &off, p, hdr.ex.a_syms))
635		return;
636	    p += hdr.ex.a_syms;
637	    if (xfsread(&dn, &off, p, sizeof(int)))
638		return;
639	    x = *(uint32_t *)p;
640	    p += sizeof(int);
641	    x -= sizeof(int);
642	    if (xfsread(&dn, &off, p, x))
643		return;
644	    p += x;
645	}
646    } else {
647	off = hdr.eh.e_phoff;
648	for (j = i = 0; i < hdr.eh.e_phnum && j < 2; i++) {
649	    if (xfsread(&dn, &off, ep + j, sizeof(ep[0])))
650		return;
651	    if (ep[j].p_type == PT_LOAD)
652		j++;
653	}
654	for (i = 0; i < 2; i++) {
655	    p = PTOV(ep[i].p_paddr & 0xffffff);
656	    off = ep[i].p_offset;
657	    if (xfsread(&dn, &off, p, ep[i].p_filesz))
658		return;
659	}
660	p += roundup2(ep[1].p_memsz, PAGE_SIZE);
661	bootinfo.bi_symtab = VTOP(p);
662	if (hdr.eh.e_shnum == hdr.eh.e_shstrndx + 3) {
663	    off = hdr.eh.e_shoff + sizeof(es[0]) *
664		(hdr.eh.e_shstrndx + 1);
665	    if (xfsread(&dn, &off, &es, sizeof(es)))
666		return;
667	    for (i = 0; i < 2; i++) {
668		memcpy(p, &es[i].sh_size, sizeof(es[i].sh_size));
669		p += sizeof(es[i].sh_size);
670		off = es[i].sh_offset;
671		if (xfsread(&dn, &off, p, es[i].sh_size))
672		    return;
673		p += es[i].sh_size;
674	    }
675	}
676	addr = hdr.eh.e_entry & 0xffffff;
677    }
678    bootinfo.bi_esymtab = VTOP(p);
679    bootinfo.bi_kernelname = VTOP(kname);
680    __exec((caddr_t)addr, RB_BOOTINFO | (opts & RBX_MASK),
681	   bootdev,
682	   KARGS_FLAGS_ZFS,
683	   (uint32_t) spa->spa_guid,
684	   (uint32_t) (spa->spa_guid >> 32),
685	   VTOP(&bootinfo));
686}
687
688static int
689parse(void)
690{
691    char *arg = cmd;
692    char *ep, *p, *q;
693    const char *cp;
694    //unsigned int drv;
695    int c, i, j;
696
697    while ((c = *arg++)) {
698	if (c == ' ' || c == '\t' || c == '\n')
699	    continue;
700	for (p = arg; *p && *p != '\n' && *p != ' ' && *p != '\t'; p++);
701	ep = p;
702	if (*p)
703	    *p++ = 0;
704	if (c == '-') {
705	    while ((c = *arg++)) {
706		if (c == 'P') {
707		    if (*(uint8_t *)PTOV(0x496) & 0x10) {
708			cp = "yes";
709		    } else {
710			opts |= OPT_SET(RBX_DUAL) | OPT_SET(RBX_SERIAL);
711			cp = "no";
712		    }
713		    printf("Keyboard: %s\n", cp);
714		    continue;
715		} else if (c == 'S') {
716		    j = 0;
717		    while ((unsigned int)(i = *arg++ - '0') <= 9)
718			j = j * 10 + i;
719		    if (j > 0 && i == -'0') {
720			comspeed = j;
721			break;
722		    }
723		    /* Fall through to error below ('S' not in optstr[]). */
724		}
725		for (i = 0; c != optstr[i]; i++)
726		    if (i == NOPT - 1)
727			return -1;
728		opts ^= OPT_SET(flags[i]);
729	    }
730	    ioctrl = OPT_CHECK(RBX_DUAL) ? (IO_SERIAL|IO_KEYBOARD) :
731		     OPT_CHECK(RBX_SERIAL) ? IO_SERIAL : IO_KEYBOARD;
732	    if (ioctrl & IO_SERIAL)
733	        sio_init(115200 / comspeed);
734	} if (c == '?') {
735	    dnode_phys_t dn;
736
737	    if (zfs_lookup(spa, arg, &dn) == 0) {
738		zap_list(spa, &dn);
739	    }
740	    return -1;
741	} else {
742	    arg--;
743
744	    /*
745	     * Report pool status if the comment is 'status'. Lets
746	     * hope no-one wants to load /status as a kernel.
747	     */
748	    if (!strcmp(arg, "status")) {
749		spa_all_status();
750		return -1;
751	    }
752
753	    /*
754	     * If there is a colon, switch pools.
755	     */
756	    q = (char *) strchr(arg, ':');
757	    if (q) {
758		spa_t *newspa;
759
760		*q++ = 0;
761		newspa = spa_find_by_name(arg);
762		if (newspa) {
763		    spa = newspa;
764		    zfs_mount_pool(spa);
765		} else {
766		    printf("\nCan't find ZFS pool %s\n", arg);
767		    return -1;
768		}
769		arg = q;
770	    }
771	    if ((i = ep - arg)) {
772		if ((size_t)i >= sizeof(kname))
773		    return -1;
774		memcpy(kname, arg, i + 1);
775	    }
776	}
777	arg = p;
778    }
779    return 0;
780}
781