/* * Copy the environment into the load area starting at (addr). * Each variable is formatted as <name>=<value>, with a single nul * separating each variable, and a double nul terminating the environment. */ vm_offset_t bi_copyenv(vm_offset_t start) { struct env_var *ep; vm_offset_t addr, last; size_t len; addr = last = start; /* Traverse the environment. */ for (ep = environ; ep != NULL; ep = ep->ev_next) { len = strlen(ep->ev_name); if (i386_copyin(ep->ev_name, addr, len) != len) break; addr += len; if (i386_copyin("=", addr, 1) != 1) break; addr++; if (ep->ev_value != NULL) { len = strlen(ep->ev_value); if (i386_copyin(ep->ev_value, addr, len) != len) break; addr += len; } if (i386_copyin("", addr, 1) != 1) break; last = ++addr; } if (i386_copyin("", last++, 1) != 1) last = start; return(last); }
/* * Copy the environment into the load area starting at (addr). * Each variable is formatted as <name>=<value>, with a single nul * separating each variable, and a double nul terminating the environment. */ vm_offset_t bi_copyenv(vm_offset_t addr) { struct env_var *ep; /* traverse the environment */ for (ep = environ; ep != NULL; ep = ep->ev_next) { i386_copyin(ep->ev_name, addr, strlen(ep->ev_name)); addr += strlen(ep->ev_name); i386_copyin("=", addr, 1); addr++; if (ep->ev_value != NULL) { i386_copyin(ep->ev_value, addr, strlen(ep->ev_value)); addr += strlen(ep->ev_value); } i386_copyin("", addr, 1); addr++; } i386_copyin("", addr, 1); addr++; return(addr); }
static int multiboot_exec(struct preloaded_file *fp) { struct preloaded_file *mfp; vm_offset_t entry; struct file_metadata *md; struct multiboot_info *mb_info = NULL; struct multiboot_mod_list *mb_mod = NULL; multiboot_memory_map_t *mmap; struct bios_smap *smap; struct devdesc *rootdev; char *cmdline = NULL; size_t len; int error, num, i; int rootfs = 0; /* flag for rootfs */ int xen = 0; /* flag for xen */ int kernel = 0; /* flag for kernel */ /* Set up base for mb_malloc. */ for (mfp = fp; mfp->f_next != NULL; mfp = mfp->f_next); /* Start info block from new page. */ last_addr = roundup(mfp->f_addr + mfp->f_size, MULTIBOOT_MOD_ALIGN); /* Allocate the multiboot struct and fill the basic details. */ mb_info = (struct multiboot_info *)PTOV(mb_malloc(sizeof (*mb_info))); bzero(mb_info, sizeof(struct multiboot_info)); mb_info->flags = MULTIBOOT_INFO_MEMORY|MULTIBOOT_INFO_BOOT_LOADER_NAME; mb_info->mem_lower = bios_basemem / 1024; mb_info->mem_upper = bios_extmem / 1024; mb_info->boot_loader_name = mb_malloc(strlen(bootprog_info) + 1); i386_copyin(bootprog_info, mb_info->boot_loader_name, strlen(bootprog_info) + 1); i386_getdev((void **)(&rootdev), NULL, NULL); if (rootdev == NULL) { printf("can't determine root device\n"); error = EINVAL; goto error; } /* * Boot image command line. If args were not provided, we need to set * args here, and that depends on image type... * Fortunately we only have following options: * 64 or 32 bit unix or xen. So we just check if f_name has unix. */ /* Do we boot xen? */ if (strstr(fp->f_name, "unix") == NULL) xen = 1; entry = fp->f_addr; num = 0; for (mfp = fp->f_next; mfp != NULL; mfp = mfp->f_next) { num++; if (mfp->f_type != NULL && strcmp(mfp->f_type, "rootfs") == 0) rootfs++; if (mfp->f_type != NULL && strcmp(mfp->f_type, "kernel") == 0) kernel++; } if (num == 0 || rootfs == 0) { /* We need at least one module - rootfs. */ printf("No rootfs module provided, aborting\n"); error = EINVAL; goto error; } if (xen == 1 && kernel == 0) { printf("No kernel module provided for xen, aborting\n"); error = EINVAL; goto error; } mb_mod = (struct multiboot_mod_list *) PTOV(last_addr); last_addr += roundup(sizeof(*mb_mod) * num, MULTIBOOT_INFO_ALIGN); bzero(mb_mod, sizeof(*mb_mod) * num); num = 0; for (mfp = fp->f_next; mfp != NULL; mfp = mfp->f_next) { mb_mod[num].mod_start = mfp->f_addr; mb_mod[num].mod_end = mfp->f_addr + mfp->f_size; if (strcmp(mfp->f_type, "kernel") == 0) { cmdline = NULL; error = mb_kernel_cmdline(mfp, rootdev, &cmdline); if (error != 0) goto error; } else { len = strlen(mfp->f_name) + 1; len += strlen(mfp->f_type) + 5 + 1; if (mfp->f_args != NULL) { len += strlen(mfp->f_args) + 1; } cmdline = malloc(len); if (cmdline == NULL) { error = ENOMEM; goto error; } if (mfp->f_args != NULL) snprintf(cmdline, len, "%s type=%s %s", mfp->f_name, mfp->f_type, mfp->f_args); else snprintf(cmdline, len, "%s type=%s", mfp->f_name, mfp->f_type); } mb_mod[num].cmdline = mb_malloc(strlen(cmdline)+1); i386_copyin(cmdline, mb_mod[num].cmdline, strlen(cmdline)+1); free(cmdline); num++; } mb_info->mods_count = num; mb_info->mods_addr = VTOP(mb_mod); mb_info->flags |= MULTIBOOT_INFO_MODS; md = file_findmetadata(fp, MODINFOMD_SMAP); if (md == NULL) { printf("no memory smap\n"); error = EINVAL; goto error; } num = md->md_size / sizeof(struct bios_smap); /* number of entries */ mmap = (multiboot_memory_map_t *)PTOV(mb_malloc(sizeof(*mmap) * num)); mb_info->mmap_length = num * sizeof(*mmap); smap = (struct bios_smap *)md->md_data; for (i = 0; i < num; i++) { mmap[i].size = sizeof(*smap); mmap[i].addr = smap[i].base; mmap[i].len = smap[i].length; mmap[i].type = smap[i].type; } mb_info->mmap_addr = VTOP(mmap); mb_info->flags |= MULTIBOOT_INFO_MEM_MAP; if (strstr(getenv("loaddev"), "net") != NULL && bootp_response != NULL) { mb_info->drives_length = bootp_response_size; mb_info->drives_addr = mb_malloc(bootp_response_size); i386_copyin(bootp_response, mb_info->drives_addr, bootp_response_size); mb_info->flags &= ~MULTIBOOT_INFO_DRIVE_INFO; } /* * Set the image command line. Need to do this as last thing, * as illumos kernel dboot_startkern will check cmdline * address as last check to find first free address. */ if (fp->f_args == NULL) { if (xen) cmdline = getenv("xen_cmdline"); else cmdline = getenv("boot-args"); if (cmdline != NULL) { fp->f_args = strdup(cmdline); if (fp->f_args == NULL) { error = ENOMEM; goto error; } } } /* * If the image is xen, we just use f_name + f_args for commandline * for unix, we need to add zfs-bootfs. */ if (xen) { len = strlen(fp->f_name) + 1; if (fp->f_args != NULL) len += strlen(fp->f_args) + 1; if (fp->f_args != NULL) { if((cmdline = malloc(len)) == NULL) { error = ENOMEM; goto error; } snprintf(cmdline, len, "%s %s", fp->f_name, fp->f_args); } else { cmdline = strdup(fp->f_name); if (cmdline == NULL) { error = ENOMEM; goto error; } } } else { cmdline = NULL; if ((error = mb_kernel_cmdline(fp, rootdev, &cmdline)) != 0) goto error; } mb_info->cmdline = mb_malloc(strlen(cmdline)+1); i386_copyin(cmdline, mb_info->cmdline, strlen(cmdline)+1); mb_info->flags |= MULTIBOOT_INFO_CMDLINE; free(cmdline); cmdline = NULL; dev_cleanup(); __exec((void *)VTOP(multiboot_tramp), MULTIBOOT_BOOTLOADER_MAGIC, (void *)entry, (void *)VTOP(mb_info)); panic("exec returned"); error: free(cmdline); return (error); }