示例#1
0
/*
 * 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);
}
示例#3
0
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);
}