]> CyberLeo.Net >> Repos - FreeBSD/releng/8.1.git/blob - sys/boot/i386/zfsboot/zfsboot.c
Copy stable/8 to releng/8.1 in preparation for 8.1-RC1.
[FreeBSD/releng/8.1.git] / sys / boot / i386 / zfsboot / zfsboot.c
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$");
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 #ifndef GPT
40 #include "zfsboot.h"
41 #endif
42 #include "lib.h"
43
44 #define IO_KEYBOARD     1
45 #define IO_SERIAL       2
46
47 #define SECOND          18      /* Circa that many ticks in a second. */
48
49 #define RBX_ASKNAME     0x0     /* -a */
50 #define RBX_SINGLE      0x1     /* -s */
51 /* 0x2 is reserved for log2(RB_NOSYNC). */
52 /* 0x3 is reserved for log2(RB_HALT). */
53 /* 0x4 is reserved for log2(RB_INITNAME). */
54 #define RBX_DFLTROOT    0x5     /* -r */
55 #define RBX_KDB         0x6     /* -d */
56 /* 0x7 is reserved for log2(RB_RDONLY). */
57 /* 0x8 is reserved for log2(RB_DUMP). */
58 /* 0x9 is reserved for log2(RB_MINIROOT). */
59 #define RBX_CONFIG      0xa     /* -c */
60 #define RBX_VERBOSE     0xb     /* -v */
61 #define RBX_SERIAL      0xc     /* -h */
62 #define RBX_CDROM       0xd     /* -C */
63 /* 0xe is reserved for log2(RB_POWEROFF). */
64 #define RBX_GDB         0xf     /* -g */
65 #define RBX_MUTE        0x10    /* -m */
66 /* 0x11 is reserved for log2(RB_SELFTEST). */
67 /* 0x12 is reserved for boot programs. */
68 /* 0x13 is reserved for boot programs. */
69 #define RBX_PAUSE       0x14    /* -p */
70 #define RBX_QUIET       0x15    /* -q */
71 #define RBX_NOINTR      0x1c    /* -n */
72 /* 0x1d is reserved for log2(RB_MULTIPLE) and is just misnamed here. */
73 #define RBX_DUAL        0x1d    /* -D */
74 /* 0x1f is reserved for log2(RB_BOOTINFO). */
75
76 /* pass: -a, -s, -r, -d, -c, -v, -h, -C, -g, -m, -p, -D */
77 #define RBX_MASK        (OPT_SET(RBX_ASKNAME) | OPT_SET(RBX_SINGLE) | \
78                         OPT_SET(RBX_DFLTROOT) | OPT_SET(RBX_KDB ) | \
79                         OPT_SET(RBX_CONFIG) | OPT_SET(RBX_VERBOSE) | \
80                         OPT_SET(RBX_SERIAL) | OPT_SET(RBX_CDROM) | \
81                         OPT_SET(RBX_GDB ) | OPT_SET(RBX_MUTE) | \
82                         OPT_SET(RBX_PAUSE) | OPT_SET(RBX_DUAL))
83
84 /* Hint to loader that we came from ZFS */
85 #define KARGS_FLAGS_ZFS         0x4
86
87 #define PATH_CONFIG     "/boot.config"
88 #define PATH_BOOT3      "/boot/zfsloader"
89 #define PATH_KERNEL     "/boot/kernel/kernel"
90
91 #define ARGS            0x900
92 #define NOPT            14
93 #define NDEV            3
94 #define V86_CY(x)       ((x) & 1)
95 #define V86_ZR(x)       ((x) & 0x40)
96
97 #define DRV_HARD        0x80
98 #define DRV_MASK        0x7f
99
100 #define TYPE_AD         0
101 #define TYPE_DA         1
102 #define TYPE_MAXHARD    TYPE_DA
103 #define TYPE_FD         2
104
105 #define OPT_SET(opt)    (1 << (opt))
106 #define OPT_CHECK(opt)  ((opts) & OPT_SET(opt))
107
108 extern uint32_t _end;
109
110 #ifdef GPT
111 static const uuid_t freebsd_zfs_uuid = GPT_ENT_TYPE_FREEBSD_ZFS;
112 #endif
113 static const char optstr[NOPT] = "DhaCcdgmnpqrsv"; /* Also 'P', 'S' */
114 static const unsigned char flags[NOPT] = {
115     RBX_DUAL,
116     RBX_SERIAL,
117     RBX_ASKNAME,
118     RBX_CDROM,
119     RBX_CONFIG,
120     RBX_KDB,
121     RBX_GDB,
122     RBX_MUTE,
123     RBX_NOINTR,
124     RBX_PAUSE,
125     RBX_QUIET,
126     RBX_DFLTROOT,
127     RBX_SINGLE,
128     RBX_VERBOSE
129 };
130
131 static const char *const dev_nm[NDEV] = {"ad", "da", "fd"};
132 static const unsigned char dev_maj[NDEV] = {30, 4, 2};
133
134 struct dsk {
135     unsigned drive;
136     unsigned type;
137     unsigned unit;
138     unsigned slice;
139     unsigned part;
140     int init;
141     daddr_t start;
142 };
143 static char cmd[512];
144 static char kname[1024];
145 static uint32_t opts;
146 static int comspeed = SIOSPD;
147 static struct bootinfo bootinfo;
148 static uint32_t bootdev;
149 static uint8_t ioctrl = IO_KEYBOARD;
150
151 vm_offset_t     high_heap_base;
152 uint32_t        bios_basemem, bios_extmem, high_heap_size;
153
154 static struct bios_smap smap;
155
156 /*
157  * The minimum amount of memory to reserve in bios_extmem for the heap.
158  */
159 #define HEAP_MIN        (3 * 1024 * 1024)
160
161 static char *heap_next;
162 static char *heap_end;
163
164 /* Buffers that must not span a 64k boundary. */
165 #define READ_BUF_SIZE   8192
166 struct dmadat {
167         char rdbuf[READ_BUF_SIZE];      /* for reading large things */
168         char secbuf[READ_BUF_SIZE];     /* for MBR/disklabel */
169 };
170 static struct dmadat *dmadat;
171
172 void exit(int);
173 static void load(void);
174 static int parse(void);
175 static void printf(const char *,...);
176 static void putchar(int);
177 static void bios_getmem(void);
178 static int drvread(struct dsk *, void *, daddr_t, unsigned);
179 static int keyhit(unsigned);
180 static int xputc(int);
181 static int xgetc(int);
182 static int getc(int);
183
184 static void memcpy(void *, const void *, int);
185 static void
186 memcpy(void *dst, const void *src, int len)
187 {
188     const char *s = src;
189     char *d = dst;
190
191     while (len--)
192         *d++ = *s++;
193 }
194
195 static void
196 strcpy(char *dst, const char *src)
197 {
198     while (*src)
199         *dst++ = *src++;
200     *dst++ = 0;
201 }
202
203 static void
204 strcat(char *dst, const char *src)
205 {
206     while (*dst)
207         dst++;
208     while (*src)
209         *dst++ = *src++;
210     *dst++ = 0;
211 }
212
213 static int
214 strcmp(const char *s1, const char *s2)
215 {
216     for (; *s1 == *s2 && *s1; s1++, s2++);
217     return (unsigned char)*s1 - (unsigned char)*s2;
218 }
219
220 static const char *
221 strchr(const char *s, char ch)
222 {
223     for (; *s; s++)
224         if (*s == ch)
225                 return s;
226     return 0;
227 }
228
229 static int
230 memcmp(const void *p1, const void *p2, size_t n)
231 {
232     const char *s1 = (const char *) p1;
233     const char *s2 = (const char *) p2;
234     for (; n > 0 && *s1 == *s2; s1++, s2++, n--);
235     if (n)
236         return (unsigned char)*s1 - (unsigned char)*s2;
237     else
238         return 0;
239 }
240
241 static void
242 memset(void *p, char val, size_t n)
243 {
244     char *s = (char *) p;
245     while (n--)
246         *s++ = val;
247 }
248
249 static void *
250 malloc(size_t n)
251 {
252         char *p = heap_next;
253         if (p + n > heap_end) {
254                 printf("malloc failure\n");
255                 for (;;)
256                     ;
257                 return 0;
258         }
259         heap_next += n;
260         return p;
261 }
262
263 static size_t
264 strlen(const char *s)
265 {
266         size_t len = 0;
267         while (*s++)
268                 len++;
269         return len;
270 }
271
272 static char *
273 strdup(const char *s)
274 {
275         char *p = malloc(strlen(s) + 1);
276         strcpy(p, s);
277         return p;
278 }
279
280 #include "zfsimpl.c"
281
282 /*
283  * Read from a dnode (which must be from a ZPL filesystem).
284  */
285 static int
286 zfs_read(spa_t *spa, const dnode_phys_t *dnode, off_t *offp, void *start, size_t size)
287 {
288         const znode_phys_t *zp = (const znode_phys_t *) dnode->dn_bonus;
289         size_t n;
290         int rc;
291
292         n = size;
293         if (*offp + n > zp->zp_size)
294                 n = zp->zp_size - *offp;
295         
296         rc = dnode_read(spa, dnode, *offp, start, n);
297         if (rc)
298                 return (-1);
299         *offp += n;
300
301         return (n);
302 }
303
304 /*
305  * Current ZFS pool
306  */
307 spa_t *spa;
308
309 /*
310  * A wrapper for dskread that doesn't have to worry about whether the
311  * buffer pointer crosses a 64k boundary.
312  */
313 static int
314 vdev_read(vdev_t *vdev, void *priv, off_t off, void *buf, size_t bytes)
315 {
316         char *p;
317         daddr_t lba;
318         unsigned int nb;
319         struct dsk *dsk = (struct dsk *) priv;
320
321         if ((off & (DEV_BSIZE - 1)) || (bytes & (DEV_BSIZE - 1)))
322                 return -1;
323
324         p = buf;
325         lba = off / DEV_BSIZE;
326         while (bytes > 0) {
327                 nb = bytes / DEV_BSIZE;
328                 if (nb > READ_BUF_SIZE / DEV_BSIZE)
329                         nb = READ_BUF_SIZE / DEV_BSIZE;
330                 if (drvread(dsk, dmadat->rdbuf, lba, nb))
331                         return -1;
332                 memcpy(p, dmadat->rdbuf, nb * DEV_BSIZE);
333                 p += nb * DEV_BSIZE;
334                 lba += nb;
335                 bytes -= nb * DEV_BSIZE;
336         }
337
338         return 0;
339 }
340
341 static int
342 xfsread(const dnode_phys_t *dnode, off_t *offp, void *buf, size_t nbyte)
343 {
344     if ((size_t)zfs_read(spa, dnode, offp, buf, nbyte) != nbyte) {
345         printf("Invalid %s\n", "format");
346         return -1;
347     }
348     return 0;
349 }
350
351 static void
352 bios_getmem(void)
353 {
354     uint64_t size;
355
356     /* Parse system memory map */
357     v86.ebx = 0;
358     do {
359         v86.ctl = V86_FLAGS;
360         v86.addr = 0x15;                /* int 0x15 function 0xe820*/
361         v86.eax = 0xe820;
362         v86.ecx = sizeof(struct bios_smap);
363         v86.edx = SMAP_SIG;
364         v86.es = VTOPSEG(&smap);
365         v86.edi = VTOPOFF(&smap);
366         v86int();
367         if ((v86.efl & 1) || (v86.eax != SMAP_SIG))
368             break;
369         /* look for a low-memory segment that's large enough */
370         if ((smap.type == SMAP_TYPE_MEMORY) && (smap.base == 0) &&
371             (smap.length >= (512 * 1024)))
372             bios_basemem = smap.length;
373         /* look for the first segment in 'extended' memory */
374         if ((smap.type == SMAP_TYPE_MEMORY) && (smap.base == 0x100000)) {
375             bios_extmem = smap.length;
376         }
377
378         /*
379          * Look for the largest segment in 'extended' memory beyond
380          * 1MB but below 4GB.
381          */
382         if ((smap.type == SMAP_TYPE_MEMORY) && (smap.base > 0x100000) &&
383             (smap.base < 0x100000000ull)) {
384             size = smap.length;
385
386             /*
387              * If this segment crosses the 4GB boundary, truncate it.
388              */
389             if (smap.base + size > 0x100000000ull)
390                 size = 0x100000000ull - smap.base;
391
392             if (size > high_heap_size) {
393                 high_heap_size = size;
394                 high_heap_base = smap.base;
395             }
396         }
397     } while (v86.ebx != 0);
398
399     /* Fall back to the old compatibility function for base memory */
400     if (bios_basemem == 0) {
401         v86.ctl = 0;
402         v86.addr = 0x12;                /* int 0x12 */
403         v86int();
404         
405         bios_basemem = (v86.eax & 0xffff) * 1024;
406     }
407
408     /* Fall back through several compatibility functions for extended memory */
409     if (bios_extmem == 0) {
410         v86.ctl = V86_FLAGS;
411         v86.addr = 0x15;                /* int 0x15 function 0xe801*/
412         v86.eax = 0xe801;
413         v86int();
414         if (!(v86.efl & 1)) {
415             bios_extmem = ((v86.ecx & 0xffff) + ((v86.edx & 0xffff) * 64)) * 1024;
416         }
417     }
418     if (bios_extmem == 0) {
419         v86.ctl = 0;
420         v86.addr = 0x15;                /* int 0x15 function 0x88*/
421         v86.eax = 0x8800;
422         v86int();
423         bios_extmem = (v86.eax & 0xffff) * 1024;
424     }
425
426     /*
427      * If we have extended memory and did not find a suitable heap
428      * region in the SMAP, use the last 3MB of 'extended' memory as a
429      * high heap candidate.
430      */
431     if (bios_extmem >= HEAP_MIN && high_heap_size < HEAP_MIN) {
432         high_heap_size = HEAP_MIN;
433         high_heap_base = bios_extmem + 0x100000 - HEAP_MIN;
434     }
435 }    
436
437 static inline void
438 getstr(void)
439 {
440     char *s;
441     int c;
442
443     s = cmd;
444     for (;;) {
445         switch (c = xgetc(0)) {
446         case 0:
447             break;
448         case '\177':
449         case '\b':
450             if (s > cmd) {
451                 s--;
452                 printf("\b \b");
453             }
454             break;
455         case '\n':
456         case '\r':
457             *s = 0;
458             return;
459         default:
460             if (s - cmd < sizeof(cmd) - 1)
461                 *s++ = c;
462             putchar(c);
463         }
464     }
465 }
466
467 static inline void
468 putc(int c)
469 {
470     v86.addr = 0x10;
471     v86.eax = 0xe00 | (c & 0xff);
472     v86.ebx = 0x7;
473     v86int();
474 }
475
476 /*
477  * Try to detect a device supported by the legacy int13 BIOS
478  */
479 static int
480 int13probe(int drive)
481 {
482     v86.ctl = V86_FLAGS;
483     v86.addr = 0x13;
484     v86.eax = 0x800;
485     v86.edx = drive;
486     v86int();
487     
488     if (!(v86.efl & 0x1) &&                             /* carry clear */
489         ((v86.edx & 0xff) != (drive & DRV_MASK))) {     /* unit # OK */
490         if ((v86.ecx & 0x3f) == 0) {                    /* absurd sector size */
491                 return(0);                              /* skip device */
492         }
493         return (1);
494     }
495     return(0);
496 }
497
498 /*
499  * We call this when we find a ZFS vdev - ZFS consumes the dsk
500  * structure so we must make a new one.
501  */
502 static struct dsk *
503 copy_dsk(struct dsk *dsk)
504 {
505     struct dsk *newdsk;
506
507     newdsk = malloc(sizeof(struct dsk));
508     *newdsk = *dsk;
509     return (newdsk);
510 }
511
512 static void
513 probe_drive(struct dsk *dsk, spa_t **spap)
514 {
515 #ifdef GPT
516     struct gpt_hdr hdr;
517     struct gpt_ent *ent;
518     daddr_t slba, elba;
519     unsigned part, entries_per_sec;
520 #endif
521     struct dos_partition *dp;
522     char *sec;
523     unsigned i;
524
525     /*
526      * If we find a vdev on the whole disk, stop here. Otherwise dig
527      * out the MBR and probe each slice in turn for a vdev.
528      */
529     if (vdev_probe(vdev_read, dsk, spap) == 0)
530         return;
531
532     sec = dmadat->secbuf;
533     dsk->start = 0;
534
535 #ifdef GPT
536     /*
537      * First check for GPT.
538      */
539     if (drvread(dsk, sec, 1, 1)) {
540         return;
541     }
542     memcpy(&hdr, sec, sizeof(hdr));
543     if (memcmp(hdr.hdr_sig, GPT_HDR_SIG, sizeof(hdr.hdr_sig)) != 0 ||
544         hdr.hdr_lba_self != 1 || hdr.hdr_revision < 0x00010000 ||
545         hdr.hdr_entsz < sizeof(*ent) || DEV_BSIZE % hdr.hdr_entsz != 0) {
546         goto trymbr;
547     }
548
549     /*
550      * Probe all GPT partitions for the presense of ZFS pools. We
551      * return the spa_t for the first we find (if requested). This
552      * will have the effect of booting from the first pool on the
553      * disk.
554      */
555     entries_per_sec = DEV_BSIZE / hdr.hdr_entsz;
556     slba = hdr.hdr_lba_table;
557     elba = slba + hdr.hdr_entries / entries_per_sec;
558     while (slba < elba) {
559         dsk->start = 0;
560         if (drvread(dsk, sec, slba, 1))
561             return;
562         for (part = 0; part < entries_per_sec; part++) {
563             ent = (struct gpt_ent *)(sec + part * hdr.hdr_entsz);
564             if (memcmp(&ent->ent_type, &freebsd_zfs_uuid,
565                      sizeof(uuid_t)) == 0) {
566                 dsk->start = ent->ent_lba_start;
567                 if (vdev_probe(vdev_read, dsk, spap) == 0) {
568                     /*
569                      * We record the first pool we find (we will try
570                      * to boot from that one).
571                      */
572                     spap = 0;
573
574                     /*
575                      * This slice had a vdev. We need a new dsk
576                      * structure now since the vdev now owns this one.
577                      */
578                     dsk = copy_dsk(dsk);
579                 }
580             }
581         }
582         slba++;
583     }
584     return;
585 trymbr:
586 #endif
587
588     if (drvread(dsk, sec, DOSBBSECTOR, 1))
589         return;
590     dp = (void *)(sec + DOSPARTOFF);
591
592     for (i = 0; i < NDOSPART; i++) {
593         if (!dp[i].dp_typ)
594             continue;
595         dsk->start = dp[i].dp_start;
596         if (vdev_probe(vdev_read, dsk, spap) == 0) {
597             /*
598              * We record the first pool we find (we will try to boot
599              * from that one.
600              */
601             spap = 0;
602
603             /*
604              * This slice had a vdev. We need a new dsk structure now
605              * since the vdev now owns this one.
606              */
607             dsk = copy_dsk(dsk);
608         }
609     }
610 }
611
612 int
613 main(void)
614 {
615     int autoboot, i;
616     dnode_phys_t dn;
617     off_t off;
618     struct dsk *dsk;
619
620     bios_getmem();
621
622     if (high_heap_size > 0) {
623         heap_end = PTOV(high_heap_base + high_heap_size);
624         heap_next = PTOV(high_heap_base);
625     } else {
626         heap_next = (char *) dmadat + sizeof(*dmadat);
627         heap_end = (char *) PTOV(bios_basemem);
628     }
629
630     dmadat = (void *)(roundup2(__base + (int32_t)&_end, 0x10000) - __base);
631     v86.ctl = V86_FLAGS;
632
633     dsk = malloc(sizeof(struct dsk));
634     dsk->drive = *(uint8_t *)PTOV(ARGS);
635     dsk->type = dsk->drive & DRV_HARD ? TYPE_AD : TYPE_FD;
636     dsk->unit = dsk->drive & DRV_MASK;
637     dsk->slice = *(uint8_t *)PTOV(ARGS + 1) + 1;
638     dsk->part = 0;
639     dsk->start = 0;
640     dsk->init = 0;
641
642     bootinfo.bi_version = BOOTINFO_VERSION;
643     bootinfo.bi_size = sizeof(bootinfo);
644     bootinfo.bi_basemem = bios_basemem / 1024;
645     bootinfo.bi_extmem = bios_extmem / 1024;
646     bootinfo.bi_memsizes_valid++;
647     bootinfo.bi_bios_dev = dsk->drive;
648
649     bootdev = MAKEBOOTDEV(dev_maj[dsk->type],
650                           dsk->slice, dsk->unit, dsk->part),
651
652     /* Process configuration file */
653
654     autoboot = 1;
655
656     zfs_init();
657
658     /*
659      * Probe the boot drive first - we will try to boot from whatever
660      * pool we find on that drive.
661      */
662     probe_drive(dsk, &spa);
663
664     /*
665      * Probe the rest of the drives that the bios knows about. This
666      * will find any other available pools and it may fill in missing
667      * vdevs for the boot pool.
668      */
669     for (i = 0; i < 128; i++) {
670         if ((i | DRV_HARD) == *(uint8_t *)PTOV(ARGS))
671             continue;
672
673         if (!int13probe(i | DRV_HARD))
674             break;
675
676         dsk = malloc(sizeof(struct dsk));
677         dsk->drive = i | DRV_HARD;
678         dsk->type = dsk->drive & TYPE_AD;
679         dsk->unit = i;
680         dsk->slice = 0;
681         dsk->part = 0;
682         dsk->start = 0;
683         dsk->init = 0;
684         probe_drive(dsk, 0);
685     }
686
687     /*
688      * If we didn't find a pool on the boot drive, default to the
689      * first pool we found, if any.
690      */
691     if (!spa) {
692         spa = STAILQ_FIRST(&zfs_pools);
693         if (!spa) {
694             printf("No ZFS pools located, can't boot\n");
695             for (;;)
696                 ;
697         }
698     }
699
700     zfs_mount_pool(spa);
701
702     if (zfs_lookup(spa, PATH_CONFIG, &dn) == 0) {
703         off = 0;
704         zfs_read(spa, &dn, &off, cmd, sizeof(cmd));
705     }
706
707     if (*cmd) {
708         if (parse())
709             autoboot = 0;
710         if (!OPT_CHECK(RBX_QUIET))
711             printf("%s: %s", PATH_CONFIG, cmd);
712         /* Do not process this command twice */
713         *cmd = 0;
714     }
715
716     /*
717      * Try to exec stage 3 boot loader. If interrupted by a keypress,
718      * or in case of failure, try to load a kernel directly instead.
719      */
720
721     if (autoboot && !*kname) {
722         memcpy(kname, PATH_BOOT3, sizeof(PATH_BOOT3));
723         if (!keyhit(3*SECOND)) {
724             load();
725             memcpy(kname, PATH_KERNEL, sizeof(PATH_KERNEL));
726         }
727     }
728
729     /* Present the user with the boot2 prompt. */
730
731     for (;;) {
732         if (!autoboot || !OPT_CHECK(RBX_QUIET))
733             printf("\nFreeBSD/i386 boot\n"
734                    "Default: %s:%s\n"
735                    "boot: ",
736                    spa->spa_name, kname);
737         if (ioctrl & IO_SERIAL)
738             sio_flush();
739         if (!autoboot || keyhit(5*SECOND))
740             getstr();
741         else if (!autoboot || !OPT_CHECK(RBX_QUIET))
742             putchar('\n');
743         autoboot = 0;
744         if (parse())
745             putchar('\a');
746         else
747             load();
748     }
749 }
750
751 /* XXX - Needed for btxld to link the boot2 binary; do not remove. */
752 void
753 exit(int x)
754 {
755 }
756
757 static void
758 load(void)
759 {
760     union {
761         struct exec ex;
762         Elf32_Ehdr eh;
763     } hdr;
764     static Elf32_Phdr ep[2];
765     static Elf32_Shdr es[2];
766     caddr_t p;
767     dnode_phys_t dn;
768     off_t off;
769     uint32_t addr, x;
770     int fmt, i, j;
771
772     if (zfs_lookup(spa, kname, &dn)) {
773         return;
774     }
775     off = 0;
776     if (xfsread(&dn, &off, &hdr, sizeof(hdr)))
777         return;
778     if (N_GETMAGIC(hdr.ex) == ZMAGIC)
779         fmt = 0;
780     else if (IS_ELF(hdr.eh))
781         fmt = 1;
782     else {
783         printf("Invalid %s\n", "format");
784         return;
785     }
786     if (fmt == 0) {
787         addr = hdr.ex.a_entry & 0xffffff;
788         p = PTOV(addr);
789         off = PAGE_SIZE;
790         if (xfsread(&dn, &off, p, hdr.ex.a_text))
791             return;
792         p += roundup2(hdr.ex.a_text, PAGE_SIZE);
793         if (xfsread(&dn, &off, p, hdr.ex.a_data))
794             return;
795         p += hdr.ex.a_data + roundup2(hdr.ex.a_bss, PAGE_SIZE);
796         bootinfo.bi_symtab = VTOP(p);
797         memcpy(p, &hdr.ex.a_syms, sizeof(hdr.ex.a_syms));
798         p += sizeof(hdr.ex.a_syms);
799         if (hdr.ex.a_syms) {
800             if (xfsread(&dn, &off, p, hdr.ex.a_syms))
801                 return;
802             p += hdr.ex.a_syms;
803             if (xfsread(&dn, &off, p, sizeof(int)))
804                 return;
805             x = *(uint32_t *)p;
806             p += sizeof(int);
807             x -= sizeof(int);
808             if (xfsread(&dn, &off, p, x))
809                 return;
810             p += x;
811         }
812     } else {
813         off = hdr.eh.e_phoff;
814         for (j = i = 0; i < hdr.eh.e_phnum && j < 2; i++) {
815             if (xfsread(&dn, &off, ep + j, sizeof(ep[0])))
816                 return;
817             if (ep[j].p_type == PT_LOAD)
818                 j++;
819         }
820         for (i = 0; i < 2; i++) {
821             p = PTOV(ep[i].p_paddr & 0xffffff);
822             off = ep[i].p_offset;
823             if (xfsread(&dn, &off, p, ep[i].p_filesz))
824                 return;
825         }
826         p += roundup2(ep[1].p_memsz, PAGE_SIZE);
827         bootinfo.bi_symtab = VTOP(p);
828         if (hdr.eh.e_shnum == hdr.eh.e_shstrndx + 3) {
829             off = hdr.eh.e_shoff + sizeof(es[0]) *
830                 (hdr.eh.e_shstrndx + 1);
831             if (xfsread(&dn, &off, &es, sizeof(es)))
832                 return;
833             for (i = 0; i < 2; i++) {
834                 memcpy(p, &es[i].sh_size, sizeof(es[i].sh_size));
835                 p += sizeof(es[i].sh_size);
836                 off = es[i].sh_offset;
837                 if (xfsread(&dn, &off, p, es[i].sh_size))
838                     return;
839                 p += es[i].sh_size;
840             }
841         }
842         addr = hdr.eh.e_entry & 0xffffff;
843     }
844     bootinfo.bi_esymtab = VTOP(p);
845     bootinfo.bi_kernelname = VTOP(kname);
846     __exec((caddr_t)addr, RB_BOOTINFO | (opts & RBX_MASK),
847            bootdev,
848            KARGS_FLAGS_ZFS,
849            (uint32_t) spa->spa_guid,
850            (uint32_t) (spa->spa_guid >> 32),
851            VTOP(&bootinfo));
852 }
853
854 static int
855 parse()
856 {
857     char *arg = cmd;
858     char *ep, *p, *q;
859     const char *cp;
860     //unsigned int drv;
861     int c, i, j;
862
863     while ((c = *arg++)) {
864         if (c == ' ' || c == '\t' || c == '\n')
865             continue;
866         for (p = arg; *p && *p != '\n' && *p != ' ' && *p != '\t'; p++);
867         ep = p;
868         if (*p)
869             *p++ = 0;
870         if (c == '-') {
871             while ((c = *arg++)) {
872                 if (c == 'P') {
873                     if (*(uint8_t *)PTOV(0x496) & 0x10) {
874                         cp = "yes";
875                     } else {
876                         opts |= OPT_SET(RBX_DUAL) | OPT_SET(RBX_SERIAL);
877                         cp = "no";
878                     }
879                     printf("Keyboard: %s\n", cp);
880                     continue;
881                 } else if (c == 'S') {
882                     j = 0;
883                     while ((unsigned int)(i = *arg++ - '0') <= 9)
884                         j = j * 10 + i;
885                     if (j > 0 && i == -'0') {
886                         comspeed = j;
887                         break;
888                     }
889                     /* Fall through to error below ('S' not in optstr[]). */
890                 }
891                 for (i = 0; c != optstr[i]; i++)
892                     if (i == NOPT - 1)
893                         return -1;
894                 opts ^= OPT_SET(flags[i]);
895             }
896             ioctrl = OPT_CHECK(RBX_DUAL) ? (IO_SERIAL|IO_KEYBOARD) :
897                      OPT_CHECK(RBX_SERIAL) ? IO_SERIAL : IO_KEYBOARD;
898             if (ioctrl & IO_SERIAL)
899                 sio_init(115200 / comspeed);
900         } if (c == '?') {
901             dnode_phys_t dn;
902
903             if (zfs_lookup(spa, arg, &dn) == 0) {
904                 zap_list(spa, &dn);
905             }
906             return -1;
907         } else {
908             arg--;
909
910             /*
911              * Report pool status if the comment is 'status'. Lets
912              * hope no-one wants to load /status as a kernel.
913              */
914             if (!strcmp(arg, "status")) {
915                 spa_all_status();
916                 return -1;
917             }
918
919             /*
920              * If there is a colon, switch pools.
921              */
922             q = (char *) strchr(arg, ':');
923             if (q) {
924                 spa_t *newspa;
925
926                 *q++ = 0;
927                 newspa = spa_find_by_name(arg);
928                 if (newspa) {
929                     spa = newspa;
930                     zfs_mount_pool(spa);
931                 } else {
932                     printf("\nCan't find ZFS pool %s\n", arg);
933                     return -1;
934                 }
935                 arg = q;
936             }
937             if ((i = ep - arg)) {
938                 if ((size_t)i >= sizeof(kname))
939                     return -1;
940                 memcpy(kname, arg, i + 1);
941             }
942         }
943         arg = p;
944     }
945     return 0;
946 }
947
948 static void
949 printf(const char *fmt,...)
950 {
951     va_list ap;
952     char buf[20];
953     char *s;
954     unsigned long long u;
955     int c;
956     int minus;
957     int prec;
958     int l;
959     int len;
960     int pad;
961
962     va_start(ap, fmt);
963     while ((c = *fmt++)) {
964         if (c == '%') {
965             minus = 0;
966             prec = 0;
967             l = 0;
968         nextfmt:
969             c = *fmt++;
970             switch (c) {
971             case '-':
972                 minus = 1;
973                 goto nextfmt;
974             case '0':
975             case '1':
976             case '2':
977             case '3':
978             case '4':
979             case '5':
980             case '6':
981             case '7':
982             case '8':
983             case '9':
984                 prec = 10 * prec + (c - '0');
985                 goto nextfmt;
986             case 'c':
987                 putchar(va_arg(ap, int));
988                 continue;
989             case 'l':
990                 l++;
991                 goto nextfmt;
992             case 's':
993                 s = va_arg(ap, char *);
994                 if (prec) {
995                     len = strlen(s);
996                     if (len < prec)
997                         pad = prec - len;
998                     else
999                         pad = 0;
1000                     if (minus)
1001                         while (pad--)
1002                             putchar(' ');
1003                     for (; *s; s++)
1004                         putchar(*s);
1005                     if (!minus)
1006                         while (pad--)
1007                             putchar(' ');
1008                 } else {
1009                     for (; *s; s++)
1010                         putchar(*s);
1011                 }
1012                 continue;
1013             case 'u':
1014                 switch (l) {
1015                 case 2:
1016                     u = va_arg(ap, unsigned long long);
1017                     break;
1018                 case 1:
1019                     u = va_arg(ap, unsigned long);
1020                     break;
1021                 default:
1022                     u = va_arg(ap, unsigned);
1023                     break;
1024                 }
1025                 s = buf;
1026                 do
1027                     *s++ = '0' + u % 10U;
1028                 while (u /= 10U);
1029                 while (--s >= buf)
1030                     putchar(*s);
1031                 continue;
1032             }
1033         }
1034         putchar(c);
1035     }
1036     va_end(ap);
1037     return;
1038 }
1039
1040 static void
1041 putchar(int c)
1042 {
1043     if (c == '\n')
1044         xputc('\r');
1045     xputc(c);
1046 }
1047
1048 #ifdef GPT
1049 static struct {
1050         uint16_t len;
1051         uint16_t count;
1052         uint16_t off;
1053         uint16_t seg;
1054         uint64_t lba;
1055 } packet;
1056 #endif
1057
1058 static int
1059 drvread(struct dsk *dsk, void *buf, daddr_t lba, unsigned nblk)
1060 {
1061 #ifdef GPT
1062     static unsigned c = 0x2d5c7c2f;
1063
1064     if (!OPT_CHECK(RBX_QUIET))
1065         printf("%c\b", c = c << 8 | c >> 24);
1066     packet.len = 0x10;
1067     packet.count = nblk;
1068     packet.off = VTOPOFF(buf);
1069     packet.seg = VTOPSEG(buf);
1070     packet.lba = lba + dsk->start;
1071     v86.ctl = V86_FLAGS;
1072     v86.addr = 0x13;
1073     v86.eax = 0x4200;
1074     v86.edx = dsk->drive;
1075     v86.ds = VTOPSEG(&packet);
1076     v86.esi = VTOPOFF(&packet);
1077     v86int();
1078     if (V86_CY(v86.efl)) {
1079         printf("error %u lba %u\n", v86.eax >> 8 & 0xff, lba);
1080         return -1;
1081     }
1082     return 0;
1083 #else
1084     static unsigned c = 0x2d5c7c2f;
1085
1086     lba += dsk->start;
1087     if (!OPT_CHECK(RBX_QUIET))
1088         printf("%c\b", c = c << 8 | c >> 24);
1089     v86.ctl = V86_ADDR | V86_CALLF | V86_FLAGS;
1090     v86.addr = XREADORG;                /* call to xread in boot1 */
1091     v86.es = VTOPSEG(buf);
1092     v86.eax = lba;
1093     v86.ebx = VTOPOFF(buf);
1094     v86.ecx = lba >> 32;
1095     v86.edx = nblk << 8 | dsk->drive;
1096     v86int();
1097     v86.ctl = V86_FLAGS;
1098     if (V86_CY(v86.efl)) {
1099         printf("error %u lba %u\n", v86.eax >> 8 & 0xff, lba);
1100         return -1;
1101     }
1102     return 0;
1103 #endif
1104 }
1105
1106 static int
1107 keyhit(unsigned ticks)
1108 {
1109     uint32_t t0, t1;
1110
1111     if (OPT_CHECK(RBX_NOINTR))
1112         return 0;
1113     t0 = 0;
1114     for (;;) {
1115         if (xgetc(1))
1116             return 1;
1117         t1 = *(uint32_t *)PTOV(0x46c);
1118         if (!t0)
1119             t0 = t1;
1120         if (t1 < t0 || t1 >= t0 + ticks)
1121             return 0;
1122     }
1123 }
1124
1125 static int
1126 xputc(int c)
1127 {
1128     if (ioctrl & IO_KEYBOARD)
1129         putc(c);
1130     if (ioctrl & IO_SERIAL)
1131         sio_putc(c);
1132     return c;
1133 }
1134
1135 static int
1136 xgetc(int fn)
1137 {
1138     if (OPT_CHECK(RBX_NOINTR))
1139         return 0;
1140     for (;;) {
1141         if (ioctrl & IO_KEYBOARD && getc(1))
1142             return fn ? 1 : getc(0);
1143         if (ioctrl & IO_SERIAL && sio_ischar())
1144             return fn ? 1 : sio_getc();
1145         if (fn)
1146             return 0;
1147     }
1148 }
1149
1150 static int
1151 getc(int fn)
1152 {
1153     /*
1154      * The extra comparison against zero is an attempt to work around
1155      * what appears to be a bug in QEMU and Bochs. Both emulators
1156      * sometimes report a key-press with scancode one and ascii zero
1157      * when no such key is pressed in reality. As far as I can tell,
1158      * this only happens shortly after a reboot.
1159      */
1160     v86.addr = 0x16;
1161     v86.eax = fn << 8;
1162     v86int();
1163     return fn == 0 ? v86.eax & 0xff : (!V86_ZR(v86.efl) && (v86.eax & 0xff));
1164 }