1*10a86925SToomas Soome /* 2*10a86925SToomas Soome * Copyright (c) 2011 Google, Inc. 3*10a86925SToomas Soome * All rights reserved. 4*10a86925SToomas Soome * 5*10a86925SToomas Soome * Redistribution and use in source and binary forms, with or without 6*10a86925SToomas Soome * modification, are permitted provided that the following conditions 7*10a86925SToomas Soome * are met: 8*10a86925SToomas Soome * 1. Redistributions of source code must retain the above copyright 9*10a86925SToomas Soome * notice, this list of conditions and the following disclaimer. 10*10a86925SToomas Soome * 2. Redistributions in binary form must reproduce the above copyright 11*10a86925SToomas Soome * notice, this list of conditions and the following disclaimer in the 12*10a86925SToomas Soome * documentation and/or other materials provided with the distribution. 13*10a86925SToomas Soome * 14*10a86925SToomas Soome * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15*10a86925SToomas Soome * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16*10a86925SToomas Soome * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17*10a86925SToomas Soome * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18*10a86925SToomas Soome * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19*10a86925SToomas Soome * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20*10a86925SToomas Soome * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21*10a86925SToomas Soome * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22*10a86925SToomas Soome * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23*10a86925SToomas Soome * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24*10a86925SToomas Soome * SUCH DAMAGE. 25*10a86925SToomas Soome */ 26*10a86925SToomas Soome 27*10a86925SToomas Soome #include <sys/types.h> 28*10a86925SToomas Soome #include <sys/disk.h> 29*10a86925SToomas Soome #include <sys/ioctl.h> 30*10a86925SToomas Soome #include <sys/stat.h> 31*10a86925SToomas Soome #include <sys/filio.h> 32*10a86925SToomas Soome #include <dirent.h> 33*10a86925SToomas Soome #include <dlfcn.h> 34*10a86925SToomas Soome #include <err.h> 35*10a86925SToomas Soome #include <errno.h> 36*10a86925SToomas Soome #include <fcntl.h> 37*10a86925SToomas Soome #include <getopt.h> 38*10a86925SToomas Soome #include <inttypes.h> 39*10a86925SToomas Soome #include <limits.h> 40*10a86925SToomas Soome #include <stdio.h> 41*10a86925SToomas Soome #include <stdlib.h> 42*10a86925SToomas Soome #include <string.h> 43*10a86925SToomas Soome #include <termios.h> 44*10a86925SToomas Soome #include <unistd.h> 45*10a86925SToomas Soome 46*10a86925SToomas Soome #include <userboot.h> 47*10a86925SToomas Soome 48*10a86925SToomas Soome int *zfs_debug; 49*10a86925SToomas Soome 50*10a86925SToomas Soome static int script; 51*10a86925SToomas Soome static char *host_base; 52*10a86925SToomas Soome static struct termios term, oldterm; 53*10a86925SToomas Soome static char *image; 54*10a86925SToomas Soome static size_t image_size; 55*10a86925SToomas Soome 56*10a86925SToomas Soome uint64_t regs[16]; 57*10a86925SToomas Soome uint64_t pc; 58*10a86925SToomas Soome int *disk_fd; 59*10a86925SToomas Soome int disk_index = -1; 60*10a86925SToomas Soome 61*10a86925SToomas Soome void test_exit(void *arg, int v); 62*10a86925SToomas Soome 63*10a86925SToomas Soome const char * 64*10a86925SToomas Soome _umem_debug_init(void) 65*10a86925SToomas Soome { 66*10a86925SToomas Soome return ("default,verbose"); /* $UMEM_DEBUG setting */ 67*10a86925SToomas Soome } 68*10a86925SToomas Soome 69*10a86925SToomas Soome const char * 70*10a86925SToomas Soome _umem_logging_init(void) 71*10a86925SToomas Soome { 72*10a86925SToomas Soome return ("fail,contents"); /* $UMEM_LOGGING setting */ 73*10a86925SToomas Soome } 74*10a86925SToomas Soome 75*10a86925SToomas Soome /* 76*10a86925SToomas Soome * Console i/o 77*10a86925SToomas Soome */ 78*10a86925SToomas Soome 79*10a86925SToomas Soome void 80*10a86925SToomas Soome test_putc(void *arg, int ch) 81*10a86925SToomas Soome { 82*10a86925SToomas Soome char c = ch; 83*10a86925SToomas Soome 84*10a86925SToomas Soome (void) write(1, &c, 1); 85*10a86925SToomas Soome } 86*10a86925SToomas Soome 87*10a86925SToomas Soome int 88*10a86925SToomas Soome test_getc(void *arg) 89*10a86925SToomas Soome { 90*10a86925SToomas Soome char c; 91*10a86925SToomas Soome 92*10a86925SToomas Soome if (read(script, &c, 1) == 1) { 93*10a86925SToomas Soome if (c == '\n') 94*10a86925SToomas Soome c = '\r'; 95*10a86925SToomas Soome return (c); 96*10a86925SToomas Soome } 97*10a86925SToomas Soome return (-1); 98*10a86925SToomas Soome } 99*10a86925SToomas Soome 100*10a86925SToomas Soome int 101*10a86925SToomas Soome test_poll(void *arg) 102*10a86925SToomas Soome { 103*10a86925SToomas Soome int n; 104*10a86925SToomas Soome 105*10a86925SToomas Soome if (ioctl(script, FIONREAD, &n) >= 0) 106*10a86925SToomas Soome return (n > 0); 107*10a86925SToomas Soome return (0); 108*10a86925SToomas Soome } 109*10a86925SToomas Soome 110*10a86925SToomas Soome /* 111*10a86925SToomas Soome * Host filesystem i/o 112*10a86925SToomas Soome */ 113*10a86925SToomas Soome 114*10a86925SToomas Soome struct test_file { 115*10a86925SToomas Soome char *tf_name; 116*10a86925SToomas Soome int tf_isdir; 117*10a86925SToomas Soome size_t tf_size; 118*10a86925SToomas Soome struct stat tf_stat; 119*10a86925SToomas Soome union { 120*10a86925SToomas Soome int fd; 121*10a86925SToomas Soome DIR *dir; 122*10a86925SToomas Soome } tf_u; 123*10a86925SToomas Soome }; 124*10a86925SToomas Soome 125*10a86925SToomas Soome int 126*10a86925SToomas Soome test_open(void *arg, const char *filename, void **h_return) 127*10a86925SToomas Soome { 128*10a86925SToomas Soome struct test_file *tf; 129*10a86925SToomas Soome char path[PATH_MAX]; 130*10a86925SToomas Soome 131*10a86925SToomas Soome if (!host_base) 132*10a86925SToomas Soome return (ENOENT); 133*10a86925SToomas Soome 134*10a86925SToomas Soome (void) strlcpy(path, host_base, PATH_MAX); 135*10a86925SToomas Soome if (path[strlen(path) - 1] == '/') 136*10a86925SToomas Soome path[strlen(path) - 1] = 0; 137*10a86925SToomas Soome (void) strlcat(path, filename, PATH_MAX); 138*10a86925SToomas Soome tf = malloc(sizeof (struct test_file)); 139*10a86925SToomas Soome if (stat(path, &tf->tf_stat) < 0) { 140*10a86925SToomas Soome free(tf); 141*10a86925SToomas Soome return (errno); 142*10a86925SToomas Soome } 143*10a86925SToomas Soome 144*10a86925SToomas Soome tf->tf_name = strdup(path); 145*10a86925SToomas Soome tf->tf_size = tf->tf_stat.st_size; 146*10a86925SToomas Soome if (S_ISDIR(tf->tf_stat.st_mode)) { 147*10a86925SToomas Soome tf->tf_isdir = 1; 148*10a86925SToomas Soome tf->tf_u.dir = opendir(path); 149*10a86925SToomas Soome if (!tf->tf_u.dir) 150*10a86925SToomas Soome goto out; 151*10a86925SToomas Soome *h_return = tf; 152*10a86925SToomas Soome return (0); 153*10a86925SToomas Soome } 154*10a86925SToomas Soome if (S_ISREG(tf->tf_stat.st_mode)) { 155*10a86925SToomas Soome tf->tf_isdir = 0; 156*10a86925SToomas Soome tf->tf_u.fd = open(path, O_RDONLY); 157*10a86925SToomas Soome if (tf->tf_u.fd < 0) 158*10a86925SToomas Soome goto out; 159*10a86925SToomas Soome *h_return = tf; 160*10a86925SToomas Soome return (0); 161*10a86925SToomas Soome } 162*10a86925SToomas Soome 163*10a86925SToomas Soome out: 164*10a86925SToomas Soome free(tf); 165*10a86925SToomas Soome return (EINVAL); 166*10a86925SToomas Soome } 167*10a86925SToomas Soome 168*10a86925SToomas Soome int 169*10a86925SToomas Soome test_close(void *arg, void *h) 170*10a86925SToomas Soome { 171*10a86925SToomas Soome struct test_file *tf = h; 172*10a86925SToomas Soome 173*10a86925SToomas Soome if (tf->tf_isdir) 174*10a86925SToomas Soome (void) closedir(tf->tf_u.dir); 175*10a86925SToomas Soome else 176*10a86925SToomas Soome (void) close(tf->tf_u.fd); 177*10a86925SToomas Soome free(tf->tf_name); 178*10a86925SToomas Soome free(tf); 179*10a86925SToomas Soome 180*10a86925SToomas Soome return (0); 181*10a86925SToomas Soome } 182*10a86925SToomas Soome 183*10a86925SToomas Soome int 184*10a86925SToomas Soome test_isdir(void *arg, void *h) 185*10a86925SToomas Soome { 186*10a86925SToomas Soome struct test_file *tf = h; 187*10a86925SToomas Soome 188*10a86925SToomas Soome return (tf->tf_isdir); 189*10a86925SToomas Soome } 190*10a86925SToomas Soome 191*10a86925SToomas Soome int 192*10a86925SToomas Soome test_read(void *arg, void *h, void *dst, size_t size, size_t *resid_return) 193*10a86925SToomas Soome { 194*10a86925SToomas Soome struct test_file *tf = h; 195*10a86925SToomas Soome ssize_t sz; 196*10a86925SToomas Soome 197*10a86925SToomas Soome if (tf->tf_isdir) 198*10a86925SToomas Soome return (EINVAL); 199*10a86925SToomas Soome sz = read(tf->tf_u.fd, dst, size); 200*10a86925SToomas Soome if (sz < 0) 201*10a86925SToomas Soome return (EINVAL); 202*10a86925SToomas Soome *resid_return = size - sz; 203*10a86925SToomas Soome return (0); 204*10a86925SToomas Soome } 205*10a86925SToomas Soome 206*10a86925SToomas Soome int 207*10a86925SToomas Soome test_readdir(void *arg, void *h, uint32_t *fileno_return, uint8_t *type_return, 208*10a86925SToomas Soome size_t *namelen_return, char *name) 209*10a86925SToomas Soome { 210*10a86925SToomas Soome struct test_file *tf = h; 211*10a86925SToomas Soome struct dirent *dp; 212*10a86925SToomas Soome struct stat st; 213*10a86925SToomas Soome char path[PATH_MAX]; 214*10a86925SToomas Soome 215*10a86925SToomas Soome if (!tf->tf_isdir) 216*10a86925SToomas Soome return (EINVAL); 217*10a86925SToomas Soome 218*10a86925SToomas Soome dp = readdir(tf->tf_u.dir); 219*10a86925SToomas Soome if (!dp) 220*10a86925SToomas Soome return (ENOENT); 221*10a86925SToomas Soome (void) snprintf(path, sizeof (path), "%s/%s/%s", host_base, tf->tf_name, 222*10a86925SToomas Soome dp->d_name); 223*10a86925SToomas Soome if (lstat(path, &st) < 0) { 224*10a86925SToomas Soome return (errno); 225*10a86925SToomas Soome } else { 226*10a86925SToomas Soome *type_return = (st.st_mode & S_IFMT) >> 12; 227*10a86925SToomas Soome } 228*10a86925SToomas Soome 229*10a86925SToomas Soome /* 230*10a86925SToomas Soome * Note: d_namlen is in the range 0..255 and therefore less 231*10a86925SToomas Soome * than PATH_MAX so we don't need to test before copying. 232*10a86925SToomas Soome */ 233*10a86925SToomas Soome *fileno_return = dp->d_ino; 234*10a86925SToomas Soome *namelen_return = strlen(dp->d_name); 235*10a86925SToomas Soome (void) strcpy(name, dp->d_name); 236*10a86925SToomas Soome 237*10a86925SToomas Soome return (0); 238*10a86925SToomas Soome } 239*10a86925SToomas Soome 240*10a86925SToomas Soome int 241*10a86925SToomas Soome test_seek(void *arg, void *h, uint64_t offset, int whence) 242*10a86925SToomas Soome { 243*10a86925SToomas Soome struct test_file *tf = h; 244*10a86925SToomas Soome 245*10a86925SToomas Soome if (tf->tf_isdir) 246*10a86925SToomas Soome return (EINVAL); 247*10a86925SToomas Soome if (lseek(tf->tf_u.fd, offset, whence) < 0) 248*10a86925SToomas Soome return (errno); 249*10a86925SToomas Soome return (0); 250*10a86925SToomas Soome } 251*10a86925SToomas Soome 252*10a86925SToomas Soome int 253*10a86925SToomas Soome test_stat(void *arg, void *h, int *mode_return, int *uid_return, 254*10a86925SToomas Soome int *gid_return, uint64_t *size_return) 255*10a86925SToomas Soome { 256*10a86925SToomas Soome struct test_file *tf = h; 257*10a86925SToomas Soome 258*10a86925SToomas Soome *mode_return = tf->tf_stat.st_mode; 259*10a86925SToomas Soome *uid_return = tf->tf_stat.st_uid; 260*10a86925SToomas Soome *gid_return = tf->tf_stat.st_gid; 261*10a86925SToomas Soome *size_return = tf->tf_stat.st_size; 262*10a86925SToomas Soome return (0); 263*10a86925SToomas Soome } 264*10a86925SToomas Soome 265*10a86925SToomas Soome /* 266*10a86925SToomas Soome * Disk image i/o 267*10a86925SToomas Soome */ 268*10a86925SToomas Soome 269*10a86925SToomas Soome int 270*10a86925SToomas Soome test_diskwrite(void *arg, int unit, uint64_t offset, void *src, size_t size, 271*10a86925SToomas Soome size_t *resid_return) 272*10a86925SToomas Soome { 273*10a86925SToomas Soome ssize_t n; 274*10a86925SToomas Soome 275*10a86925SToomas Soome if (unit > disk_index || disk_fd[unit] == -1) 276*10a86925SToomas Soome return (EIO); 277*10a86925SToomas Soome n = pwrite(disk_fd[unit], src, size, offset); 278*10a86925SToomas Soome if (n < 0) 279*10a86925SToomas Soome return (errno); 280*10a86925SToomas Soome *resid_return = size - n; 281*10a86925SToomas Soome return (0); 282*10a86925SToomas Soome } 283*10a86925SToomas Soome 284*10a86925SToomas Soome int 285*10a86925SToomas Soome test_diskread(void *arg, int unit, uint64_t offset, void *dst, size_t size, 286*10a86925SToomas Soome size_t *resid_return) 287*10a86925SToomas Soome { 288*10a86925SToomas Soome ssize_t n; 289*10a86925SToomas Soome 290*10a86925SToomas Soome if (unit > disk_index || disk_fd[unit] == -1) 291*10a86925SToomas Soome return (EIO); 292*10a86925SToomas Soome n = pread(disk_fd[unit], dst, size, offset); 293*10a86925SToomas Soome if (n == 0) { 294*10a86925SToomas Soome printf("%s: end of disk (%ju)\n", __func__, (intmax_t)offset); 295*10a86925SToomas Soome return (EIO); 296*10a86925SToomas Soome } 297*10a86925SToomas Soome 298*10a86925SToomas Soome if (n < 0) 299*10a86925SToomas Soome return (errno); 300*10a86925SToomas Soome *resid_return = size - n; 301*10a86925SToomas Soome return (0); 302*10a86925SToomas Soome } 303*10a86925SToomas Soome 304*10a86925SToomas Soome int 305*10a86925SToomas Soome test_diskioctl(void *arg, int unit, ulong_t cmd, void *data) 306*10a86925SToomas Soome { 307*10a86925SToomas Soome struct stat sb; 308*10a86925SToomas Soome 309*10a86925SToomas Soome if (unit > disk_index || disk_fd[unit] == -1) 310*10a86925SToomas Soome return (EBADF); 311*10a86925SToomas Soome switch (cmd) { 312*10a86925SToomas Soome case DIOCGSECTORSIZE: 313*10a86925SToomas Soome *(uint_t *)data = 512; 314*10a86925SToomas Soome break; 315*10a86925SToomas Soome case DIOCGMEDIASIZE: 316*10a86925SToomas Soome if (fstat(disk_fd[unit], &sb) == 0) 317*10a86925SToomas Soome *(off_t *)data = sb.st_size; 318*10a86925SToomas Soome else 319*10a86925SToomas Soome return (ENOTTY); 320*10a86925SToomas Soome break; 321*10a86925SToomas Soome default: 322*10a86925SToomas Soome return (ENOTTY); 323*10a86925SToomas Soome } 324*10a86925SToomas Soome return (0); 325*10a86925SToomas Soome } 326*10a86925SToomas Soome 327*10a86925SToomas Soome /* 328*10a86925SToomas Soome * Guest virtual machine i/o 329*10a86925SToomas Soome * 330*10a86925SToomas Soome * Note: guest addresses are kernel virtual 331*10a86925SToomas Soome */ 332*10a86925SToomas Soome 333*10a86925SToomas Soome int 334*10a86925SToomas Soome test_copyin(void *arg, const void *from, uint64_t to, size_t size) 335*10a86925SToomas Soome { 336*10a86925SToomas Soome 337*10a86925SToomas Soome to &= 0x7fffffff; 338*10a86925SToomas Soome if (to > image_size) 339*10a86925SToomas Soome return (EFAULT); 340*10a86925SToomas Soome if (to + size > image_size) 341*10a86925SToomas Soome size = image_size - to; 342*10a86925SToomas Soome memcpy(&image[to], from, size); 343*10a86925SToomas Soome return (0); 344*10a86925SToomas Soome } 345*10a86925SToomas Soome 346*10a86925SToomas Soome int 347*10a86925SToomas Soome test_copyout(void *arg, uint64_t from, void *to, size_t size) 348*10a86925SToomas Soome { 349*10a86925SToomas Soome 350*10a86925SToomas Soome from &= 0x7fffffff; 351*10a86925SToomas Soome if (from > image_size) 352*10a86925SToomas Soome return (EFAULT); 353*10a86925SToomas Soome if (from + size > image_size) 354*10a86925SToomas Soome size = image_size - from; 355*10a86925SToomas Soome memcpy(to, &image[from], size); 356*10a86925SToomas Soome return (0); 357*10a86925SToomas Soome } 358*10a86925SToomas Soome 359*10a86925SToomas Soome void 360*10a86925SToomas Soome test_setreg(void *arg, int r, uint64_t v) 361*10a86925SToomas Soome { 362*10a86925SToomas Soome 363*10a86925SToomas Soome if (r < 0 || r >= 16) 364*10a86925SToomas Soome return; 365*10a86925SToomas Soome regs[r] = v; 366*10a86925SToomas Soome } 367*10a86925SToomas Soome 368*10a86925SToomas Soome void 369*10a86925SToomas Soome test_setmsr(void *arg, int r, uint64_t v) 370*10a86925SToomas Soome { 371*10a86925SToomas Soome } 372*10a86925SToomas Soome 373*10a86925SToomas Soome void 374*10a86925SToomas Soome test_setcr(void *arg, int r, uint64_t v) 375*10a86925SToomas Soome { 376*10a86925SToomas Soome } 377*10a86925SToomas Soome 378*10a86925SToomas Soome void 379*10a86925SToomas Soome test_setgdt(void *arg, uint64_t v, size_t sz) 380*10a86925SToomas Soome { 381*10a86925SToomas Soome } 382*10a86925SToomas Soome 383*10a86925SToomas Soome void 384*10a86925SToomas Soome test_exec(void *arg, uint64_t pc) 385*10a86925SToomas Soome { 386*10a86925SToomas Soome printf("Execute at 0x%"PRIx64"\n\r", pc); 387*10a86925SToomas Soome test_exit(arg, 0); 388*10a86925SToomas Soome } 389*10a86925SToomas Soome 390*10a86925SToomas Soome /* 391*10a86925SToomas Soome * Misc 392*10a86925SToomas Soome */ 393*10a86925SToomas Soome 394*10a86925SToomas Soome void 395*10a86925SToomas Soome test_delay(void *arg, int usec) 396*10a86925SToomas Soome { 397*10a86925SToomas Soome 398*10a86925SToomas Soome (void) usleep(usec); 399*10a86925SToomas Soome } 400*10a86925SToomas Soome 401*10a86925SToomas Soome void 402*10a86925SToomas Soome test_exit(void *arg, int v) 403*10a86925SToomas Soome { 404*10a86925SToomas Soome 405*10a86925SToomas Soome (void) tcsetattr(0, TCSAFLUSH, &oldterm); 406*10a86925SToomas Soome exit(v); 407*10a86925SToomas Soome } 408*10a86925SToomas Soome 409*10a86925SToomas Soome void 410*10a86925SToomas Soome test_getmem(void *arg, uint64_t *lowmem, uint64_t *highmem) 411*10a86925SToomas Soome { 412*10a86925SToomas Soome 413*10a86925SToomas Soome *lowmem = 128*1024*1024; 414*10a86925SToomas Soome *highmem = 0; 415*10a86925SToomas Soome } 416*10a86925SToomas Soome 417*10a86925SToomas Soome char * 418*10a86925SToomas Soome test_getenv(void *arg, int idx) 419*10a86925SToomas Soome { 420*10a86925SToomas Soome extern char **environ; 421*10a86925SToomas Soome 422*10a86925SToomas Soome return (environ[idx]); 423*10a86925SToomas Soome } 424*10a86925SToomas Soome 425*10a86925SToomas Soome struct loader_callbacks cb = { 426*10a86925SToomas Soome .putc = test_putc, 427*10a86925SToomas Soome .getc = test_getc, 428*10a86925SToomas Soome .poll = test_poll, 429*10a86925SToomas Soome 430*10a86925SToomas Soome .open = test_open, 431*10a86925SToomas Soome .close = test_close, 432*10a86925SToomas Soome .isdir = test_isdir, 433*10a86925SToomas Soome .read = test_read, 434*10a86925SToomas Soome .readdir = test_readdir, 435*10a86925SToomas Soome .seek = test_seek, 436*10a86925SToomas Soome .stat = test_stat, 437*10a86925SToomas Soome 438*10a86925SToomas Soome .diskread = test_diskread, 439*10a86925SToomas Soome .diskwrite = test_diskwrite, 440*10a86925SToomas Soome .diskioctl = test_diskioctl, 441*10a86925SToomas Soome 442*10a86925SToomas Soome .copyin = test_copyin, 443*10a86925SToomas Soome .copyout = test_copyout, 444*10a86925SToomas Soome .setreg = test_setreg, 445*10a86925SToomas Soome .setmsr = test_setmsr, 446*10a86925SToomas Soome .setcr = test_setcr, 447*10a86925SToomas Soome .setgdt = test_setgdt, 448*10a86925SToomas Soome .exec = test_exec, 449*10a86925SToomas Soome 450*10a86925SToomas Soome .delay = test_delay, 451*10a86925SToomas Soome .exit = test_exit, 452*10a86925SToomas Soome .getmem = test_getmem, 453*10a86925SToomas Soome 454*10a86925SToomas Soome .getenv = test_getenv, 455*10a86925SToomas Soome }; 456*10a86925SToomas Soome 457*10a86925SToomas Soome void 458*10a86925SToomas Soome usage(void) 459*10a86925SToomas Soome { 460*10a86925SToomas Soome 461*10a86925SToomas Soome printf("usage: [-b <userboot shared object>] [-d <disk image path>] " 462*10a86925SToomas Soome "[-h <host filesystem path>\n"); 463*10a86925SToomas Soome exit(1); 464*10a86925SToomas Soome } 465*10a86925SToomas Soome 466*10a86925SToomas Soome int 467*10a86925SToomas Soome main(int argc, char **argv) 468*10a86925SToomas Soome { 469*10a86925SToomas Soome void *h; 470*10a86925SToomas Soome void (*func)(struct loader_callbacks *, void *, int, int) __NORETURN; 471*10a86925SToomas Soome int opt; 472*10a86925SToomas Soome const char *userboot_obj = "/boot/userboot.so"; 473*10a86925SToomas Soome struct winsize ws; 474*10a86925SToomas Soome int cols = 80, rows = 24, z = 0; 475*10a86925SToomas Soome int oflag = O_RDONLY; 476*10a86925SToomas Soome char *buffer = NULL; 477*10a86925SToomas Soome 478*10a86925SToomas Soome if (ioctl(1, TIOCGWINSZ, &ws) != -1) { 479*10a86925SToomas Soome if (ws.ws_col) 480*10a86925SToomas Soome cols = ws.ws_col; 481*10a86925SToomas Soome if (ws.ws_row) 482*10a86925SToomas Soome rows = ws.ws_row; 483*10a86925SToomas Soome } 484*10a86925SToomas Soome 485*10a86925SToomas Soome (void) clearenv(); 486*10a86925SToomas Soome if (asprintf(&buffer, "%d", cols) > 0) 487*10a86925SToomas Soome (void) setenv("screen-#cols", buffer, 1); 488*10a86925SToomas Soome free(buffer); 489*10a86925SToomas Soome if (asprintf(&buffer, "%d", rows) > 0) 490*10a86925SToomas Soome (void) setenv("screen-#rows", buffer, 1); 491*10a86925SToomas Soome free(buffer); 492*10a86925SToomas Soome (void) setenv("ISADIR", "amd64", 1); 493*10a86925SToomas Soome 494*10a86925SToomas Soome while ((opt = getopt(argc, argv, "b:d:h:s:wz")) != -1) { 495*10a86925SToomas Soome switch (opt) { 496*10a86925SToomas Soome case 'b': 497*10a86925SToomas Soome userboot_obj = optarg; 498*10a86925SToomas Soome break; 499*10a86925SToomas Soome 500*10a86925SToomas Soome case 'd': 501*10a86925SToomas Soome disk_index++; 502*10a86925SToomas Soome disk_fd = reallocarray(disk_fd, disk_index + 1, 503*10a86925SToomas Soome sizeof (int)); 504*10a86925SToomas Soome disk_fd[disk_index] = open(optarg, oflag); 505*10a86925SToomas Soome if (disk_fd[disk_index] < 0) 506*10a86925SToomas Soome err(1, "Can't open disk image '%s'", optarg); 507*10a86925SToomas Soome break; 508*10a86925SToomas Soome 509*10a86925SToomas Soome case 'h': 510*10a86925SToomas Soome host_base = optarg; 511*10a86925SToomas Soome break; 512*10a86925SToomas Soome 513*10a86925SToomas Soome case 's': 514*10a86925SToomas Soome if (strcmp(optarg, "-") == 0) 515*10a86925SToomas Soome script = 0; 516*10a86925SToomas Soome else 517*10a86925SToomas Soome script = open(optarg, O_RDONLY); 518*10a86925SToomas Soome 519*10a86925SToomas Soome if (script < 0) 520*10a86925SToomas Soome err(1, "Can't open script file '%s'", optarg); 521*10a86925SToomas Soome break; 522*10a86925SToomas Soome 523*10a86925SToomas Soome case 'w': 524*10a86925SToomas Soome oflag = O_RDWR; 525*10a86925SToomas Soome break; 526*10a86925SToomas Soome 527*10a86925SToomas Soome case 'z': 528*10a86925SToomas Soome z = 1; 529*10a86925SToomas Soome break; 530*10a86925SToomas Soome 531*10a86925SToomas Soome case '?': 532*10a86925SToomas Soome usage(); 533*10a86925SToomas Soome } 534*10a86925SToomas Soome } 535*10a86925SToomas Soome 536*10a86925SToomas Soome h = dlopen(userboot_obj, RTLD_LAZY | RTLD_LOCAL); 537*10a86925SToomas Soome if (!h) { 538*10a86925SToomas Soome printf("%s\n", dlerror()); 539*10a86925SToomas Soome return (1); 540*10a86925SToomas Soome } 541*10a86925SToomas Soome func = dlsym(h, "loader_main"); 542*10a86925SToomas Soome if (!func) { 543*10a86925SToomas Soome printf("%s\n", dlerror()); 544*10a86925SToomas Soome return (1); 545*10a86925SToomas Soome } 546*10a86925SToomas Soome zfs_debug = dlsym(h, "zfs_debug"); 547*10a86925SToomas Soome if (zfs_debug != NULL) 548*10a86925SToomas Soome *zfs_debug = z; 549*10a86925SToomas Soome 550*10a86925SToomas Soome image_size = 128*1024*1024; 551*10a86925SToomas Soome image = malloc(image_size); 552*10a86925SToomas Soome 553*10a86925SToomas Soome (void) tcgetattr(0, &term); 554*10a86925SToomas Soome oldterm = term; 555*10a86925SToomas Soome term.c_iflag &= ~(ICRNL | INPCK | ISTRIP); 556*10a86925SToomas Soome term.c_lflag &= ~(ICANON | ECHO | IEXTEN); 557*10a86925SToomas Soome term.c_cflag &= ~(CSIZE | PARENB); 558*10a86925SToomas Soome term.c_cflag |= CS8; 559*10a86925SToomas Soome term.c_oflag &= ~(OPOST); 560*10a86925SToomas Soome term.c_cc[VMIN] = 1; 561*10a86925SToomas Soome term.c_cc[VTIME] = 0; 562*10a86925SToomas Soome (void) tcsetattr(0, TCSADRAIN, &term); 563*10a86925SToomas Soome 564*10a86925SToomas Soome func(&cb, NULL, USERBOOT_VERSION_3, disk_index + 1); 565*10a86925SToomas Soome } 566