Ejemplo n.º 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 (ia64_copyin(ep->ev_name, addr, len) != len)
			break;
		addr += len;
		if (ia64_copyin("=", addr, 1) != 1)
			break;
		addr++;
		if (ep->ev_value != NULL) {
			len = strlen(ep->ev_value);
			if (ia64_copyin(ep->ev_value, addr, len) != len)
				break;
			addr += len;
		}
		if (ia64_copyin("", addr, 1) != 1)
			break;
		last = ++addr;
	}

	if (ia64_copyin("", last++, 1) != 1)
		last = start;
	return(last);
}
Ejemplo n.º 2
0
/*
 * Load the information expected by the kernel.
 *
 * - The kernel environment is copied into kernel space.
 * - Module metadata are formatted and placed in kernel space.
 */
int
ia64_bootinfo(struct preloaded_file *fp, struct bootinfo **res)
{
	struct bootinfo bi;
	struct preloaded_file *xp;
	struct file_metadata *md;
	struct devdesc *rootdev;
	char *rootdevname;
	vm_offset_t addr, ssym, esym;
	int error;

	*res = NULL;
	bzero(&bi, sizeof(struct bootinfo));
	bi.bi_magic = BOOTINFO_MAGIC;
	bi.bi_version = 1;
	bi.bi_boothowto = bi_getboothowto(fp->f_args);

	/* 
	 * Allow the environment variable 'rootdev' to override the supplied
	 * device. This should perhaps go to MI code and/or have $rootdev
	 * tested/set by MI code before launching the kernel.
	 */
	rootdevname = getenv("rootdev");
	ia64_getdev((void**)&rootdev, rootdevname, NULL);
	if (rootdev != NULL) {
		/* Try reading /etc/fstab to select the root device. */
		getrootmount(ia64_fmtdev(rootdev));
		free(rootdev);
	}

	md = file_findmetadata(fp, MODINFOMD_SSYM);
	ssym = (md != NULL) ? *((vm_offset_t *)&(md->md_data)) : 0;
	md = file_findmetadata(fp, MODINFOMD_ESYM);
	esym = (md != NULL) ? *((vm_offset_t *)&(md->md_data)) : 0;
	if (ssym != 0 && esym != 0) {
		bi.bi_symtab = ssym;
		bi.bi_esymtab = esym;
	}

	/* Find the last module in the chain. */
	addr = 0;
	for (xp = file_findfile(NULL, NULL); xp != NULL; xp = xp->f_next) {
		if (addr < (xp->f_addr + xp->f_size))
			addr = xp->f_addr + xp->f_size;
	}

	addr = (addr + 15) & ~15;

	/* Copy module list and metadata. */
	bi.bi_modulep = addr;
	addr = bi_copymodules(addr);
	if (addr <= bi.bi_modulep) {
		addr = bi.bi_modulep;
		bi.bi_modulep = 0;
	}

	addr = (addr + 15) & ~15;

	/* Copy our environment. */
	bi.bi_envp = addr;
	addr = bi_copyenv(addr);
	if (addr <= bi.bi_envp) {
		addr = bi.bi_envp;
		bi.bi_envp = 0;
	}

	addr = (addr + 15) & ~15;
	bi.bi_kernend = addr;

	error = ia64_platform_bootinfo(&bi, res);
	if (error)
		return (error);

	if (IS_LEGACY_KERNEL()) {
		if (*res == NULL)
			return (EDOOFUS);

		bcopy(&bi, *res, sizeof(bi));
		return (0);
	}

	bi.bi_pbvm_pgtbl = (uintptr_t)ia64_pgtbl;
	bi.bi_pbvm_pgtblsz = ia64_pgtblsz;
	ia64_copyin((void *)bi.bi_memmap, addr, bi.bi_memmap_size);
	bi.bi_memmap = addr;
	addr = (addr + bi.bi_memmap_size + 15) & ~15;
	bi.bi_kernend = addr + sizeof(bi);	
	ia64_copyin(&bi, addr, sizeof(bi));
	*res = (void *)addr;
	return (0);
}