int
command_boot(int argc, char *argv[])
{
    struct preloaded_file	*fp;
    
    /*
     * See if the user has specified an explicit kernel to boot.
     */
    if ((argc > 1) && (argv[1][0] != '-')) {
	
	/* XXX maybe we should discard everything and start again? */
	if (file_findfile(NULL, NULL) != NULL) {
	    command_seterr("can't boot '%s', kernel module already loaded",
		argv[1]);
	    return(CMD_ERROR);
	}

	/* find/load the kernel module */
	if (file_loadkernel(argv[1], argc - 2, argv + 2) != 0)
	    return(CMD_ERROR);

	/* we have consumed all arguments */
	argc = 1;
    }

    /*
     * See if there is a kernel module already loaded
     */
    if (file_findfile(NULL, NULL) == NULL)
	if (loadakernel(0, argc - 1, argv + 1))
	    /* we have consumed all arguments */
	    argc = 1;

    /*
     * Loaded anything yet?
     */
    if ((fp = file_findfile(NULL, NULL)) == NULL) {
	command_seterr("no bootable kernel");
	return(CMD_ERROR);
    }

    /*
     * If we were given arguments, discard any previous.
     * XXX should we merge arguments?  Hard to DWIM.
     */
    if (argc > 1) {
	if (fp->f_args != NULL)	
	    free(fp->f_args);
	fp->f_args = unargv(argc - 1, argv + 1);
    }

    /* Hook for platform-specific autoloading of modules */
    if (archsw.arch_autoload() != 0)
	return(CMD_ERROR);

    /* Call the exec handler from the loader matching the kernel */
    command_seterr("%s", strerror(file_formats[fp->f_loader]->l_exec(fp)));
    return(CMD_ERROR);
}
static int
fdt_setup_fdtp()
{
	struct preloaded_file *bfp;
	int err;

	/*
	 * Find the device tree blob.
	 */
	bfp = file_findfile(NULL, "dtb");
	if (bfp == NULL) {
		command_errmsg = "no device tree blob loaded";
		return (CMD_ERROR);
	}
	fdtp = (struct fdt_header *)bfp->f_addr;

	/*
	 * Validate the blob.
	 */
	err = fdt_check_header(fdtp);
	if (err < 0) {
		if (err == -FDT_ERR_BADVERSION)
			sprintf(command_errbuf,
			    "incompatible blob version: %d, should be: %d",
			    fdt_version(fdtp), FDT_LAST_SUPPORTED_VERSION);

		else
			sprintf(command_errbuf, "error validating blob: %s",
			    fdt_strerror(err));
		return (CMD_ERROR);
	}
	return (CMD_OK);
}
/*
 * Load specified KLD. If path is omitted, then try to locate it via
 * search path.
 */
int
file_loadkernel(char *filename, int argc, char *argv[])
{
    struct preloaded_file	*fp, *last_file;
    int				err;

    /* 
     * Check if KLD already loaded
     */
    fp = file_findfile(filename, NULL);
    if (fp) {
	command_seterr("warning: KLD '%s' already loaded", filename);
	free(filename);
	return (0);
    }
    for (last_file = preloaded_files; 
	 last_file != NULL && last_file->f_next != NULL;
	 last_file = last_file->f_next)
	;

    do {
	err = file_load(filename, loadaddr, &fp);
	if (err)
	    break;
	fp->f_args = unargv(argc, argv);
	loadaddr = fp->f_addr + fp->f_size;
	file_insert_tail(fp);		/* Add to the list of loaded files */
    } while(0);
    if (err == EFTYPE)
	command_seterr("don't know how to load module '%s'", filename);
    if (err && fp)
	file_discard(fp);
    free(filename);
    return (err);
}
Exemple #4
0
vm_offset_t
md_copymodules(vm_offset_t addr, int kern64)
{
    struct preloaded_file	*fp;
    struct file_metadata	*md;
    uint64_t			scratch64;
    int				c;

    c = addr != 0;
    /* start with the first module on the list, should be the kernel */
    for (fp = file_findfile(NULL, NULL); fp != NULL; fp = fp->f_next) {

	MOD_NAME(addr, fp->f_name, c);	/* this field must come first */
	MOD_TYPE(addr, fp->f_type, c);
	if (fp->f_args)
	    MOD_ARGS(addr, fp->f_args, c);
	if (kern64) {
		scratch64 = fp->f_addr;
		MOD_ADDR(addr, scratch64, c);
		scratch64 = fp->f_size;
		MOD_SIZE(addr, scratch64, c);
	} else {
		MOD_ADDR(addr, fp->f_addr, c);
		MOD_SIZE(addr, fp->f_size, c);
	}
	for (md = fp->f_metadata; md != NULL; md = md->md_next) {
	    if (!(md->md_type & MODINFOMD_NOCOPY)) {
		MOD_METADATA(addr, md, c);
	    }
	}
    }
    MOD_END(addr, c);
    return(addr);
}
Exemple #5
0
static vm_offset_t
bi_copymodules64(vm_offset_t addr)
{
    struct preloaded_file	*fp;
    struct file_metadata	*md;
    int				c;
    u_int64_t			v;

    c = addr != 0;
    /* start with the first module on the list, should be the kernel */
    for (fp = file_findfile(NULL, NULL); fp != NULL; fp = fp->f_next) {

	MOD_NAME(addr, fp->f_name, c);	/* this field must come first */
	MOD_TYPE(addr, fp->f_type, c);
	if (fp->f_args)
	    MOD_ARGS(addr, fp->f_args, c);
	v = fp->f_addr;
	MOD_ADDR(addr, v, c);
	v = fp->f_size;
	MOD_SIZE(addr, v, c);
	for (md = fp->f_metadata; md != NULL; md = md->md_next)
	    if (!(md->md_type & MODINFOMD_NOCOPY))
		MOD_METADATA(addr, md, c);
    }
    MOD_END(addr, c);
    return(addr);
}
Exemple #6
0
int
fdt_load_dtb_file(const char * filename)
{
	struct preloaded_file *bfp, *oldbfp;
	int err;

	debugf("fdt_load_dtb_file(%s)\n", filename);

	oldbfp = file_findfile(NULL, "dtb");

	/* Attempt to load and validate a new dtb from a file. */
	if ((bfp = file_loadraw(filename, "dtb")) == NULL) {
		sprintf(command_errbuf, "failed to load file '%s'", filename);
		return (1);
	}
	if ((err = fdt_load_dtb(bfp->f_addr)) != 0) {
		file_discard(bfp);
		return (err);
	}

	/* A new dtb was validated, discard any previous file. */
	if (oldbfp)
		file_discard(oldbfp);
	return (0);
}
Exemple #7
0
static int
fdt_cmd_addr(int argc, char *argv[])
{
	struct preloaded_file *fp;
	struct fdt_header *hdr;
	const char *addr;
	char *cp;

	fdt_to_load = NULL;

	if (argc > 2)
		addr = argv[2];
	else {
		sprintf(command_errbuf, "no address specified");
		return (CMD_ERROR);
	}

	hdr = (struct fdt_header *)strtoul(addr, &cp, 16);
	if (cp == addr) {
		sprintf(command_errbuf, "Invalid address: %s", addr);
		return (CMD_ERROR);
	}

	while ((fp = file_findfile(NULL, "dtb")) != NULL) {
		file_discard(fp);
	}

	fdt_to_load = hdr;
	return (CMD_OK);
}
Exemple #8
0
static vm_offset_t
max_addr(void)
{
	struct preloaded_file	*fp;
	vm_offset_t		 addr = 0;

	for (fp = file_findfile(NULL, NULL); fp != NULL; fp = fp->f_next) {
		if (addr < (fp->f_addr + fp->f_size))
			addr = fp->f_addr + fp->f_size;
	}

	return (addr);
}
Exemple #9
0
int
fdt_setup_fdtp()
{
	struct preloaded_file *bfp;
	vm_offset_t va;
	
	debugf("fdt_setup_fdtp()\n");

	/* If we already loaded a file, use it. */
	if ((bfp = file_findfile(NULL, "dtb")) != NULL) {
		if (fdt_load_dtb(bfp->f_addr) == 0) {
			printf("Using DTB from loaded file '%s'.\n", 
			    bfp->f_name);
			return (0);
		}
	}

	/* If we were given the address of a valid blob in memory, use it. */
	if (fdt_to_load != NULL) {
		if (fdt_load_dtb_addr(fdt_to_load) == 0) {
			printf("Using DTB from memory address 0x%08X.\n",
			    (unsigned int)fdt_to_load);
			return (0);
		}
	}

	if (fdt_platform_load_dtb() == 0)
		return (0);

	/* If there is a dtb compiled into the kernel, use it. */
	if ((va = fdt_find_static_dtb()) != 0) {
		if (fdt_load_dtb(va) == 0) {
			printf("Using DTB compiled into kernel.\n");
			return (0);
		}
	}
	
	command_errmsg = "No device tree blob found!\n";
	return (1);
}
Exemple #10
0
void
ficlFindfile(FICL_VM *pVM)
{
#ifndef TESTMAIN
	char	*name;
#endif
	char	*type, *namep, *typep;
	struct	preloaded_file* fp;
	int	names, types;

#if FICL_ROBUST > 1
	vmCheckStack(pVM, 4, 1);
#endif

	types = stackPopINT(pVM->pStack);
	typep = (char*) stackPopPtr(pVM->pStack);
	names = stackPopINT(pVM->pStack);
	namep = (char*) stackPopPtr(pVM->pStack);
#ifndef TESTMAIN
	name = (char*) ficlMalloc(names+1);
	if (!name)
		vmThrowErr(pVM, "Error: out of memory");
	strncpy(name, namep, names);
	name[names] = '\0';
	type = (char*) ficlMalloc(types+1);
	if (!type)
		vmThrowErr(pVM, "Error: out of memory");
	strncpy(type, typep, types);
	type[types] = '\0';

	fp = file_findfile(name, type);
#else
	fp = NULL;
#endif
	stackPushPtr(pVM->pStack, fp);

	return;
}
Exemple #11
0
vm_offset_t
bi_copymodules(vm_offset_t addr)
{
	struct preloaded_file *fp;
	struct file_metadata *md;

	/* Start with the first module on the list, should be the kernel. */
	for (fp = file_findfile(NULL, NULL); fp != NULL; fp = fp->f_next) {
		/* The name field must come first. */
		MOD_NAME(addr, fp->f_name);
		MOD_TYPE(addr, fp->f_type);
		if (fp->f_args)
			MOD_ARGS(addr, fp->f_args);
		MOD_ADDR(addr, fp->f_addr);
		MOD_SIZE(addr, fp->f_size);
		for (md = fp->f_metadata; md != NULL; md = md->md_next) {
			if (!(md->md_type & MODINFOMD_NOCOPY))
				MOD_METADATA(addr, md);
		}
	}
	MOD_END(addr);
	return(addr);
}
Exemple #12
0
static vm_offset_t
fdt_find_static_dtb(void)
{
	Elf_Sym sym;
	vm_offset_t dyntab, esym;
	uint64_t offs;
	struct preloaded_file *kfp;
	struct file_metadata *md;
	Elf_Sym *symtab;
	Elf_Dyn *dyn;
	char *strtab, *strp;
	int i, sym_count;

	symtab = NULL;
	dyntab = esym = 0;
	strtab = strp = NULL;

	offs = __elfN(relocation_offset);

	kfp = file_findfile(NULL, NULL);
	if (kfp == NULL)
		return (0);

	md = file_findmetadata(kfp, MODINFOMD_ESYM);
	if (md == NULL)
		return (0);
	COPYOUT(md->md_data, &esym, sizeof(esym));

	md = file_findmetadata(kfp, MODINFOMD_DYNAMIC);
	if (md == NULL)
		return (0);
	COPYOUT(md->md_data, &dyntab, sizeof(dyntab));

	dyntab += offs;

	/* Locate STRTAB and DYNTAB */
	for (dyn = (Elf_Dyn *)dyntab; dyn->d_tag != DT_NULL; dyn++) {
		if (dyn->d_tag == DT_STRTAB) {
			strtab = (char *)(uintptr_t)(dyn->d_un.d_ptr + offs);
			continue;
		} else if (dyn->d_tag == DT_SYMTAB) {
			symtab = (Elf_Sym *)(uintptr_t)
			    (dyn->d_un.d_ptr + offs);
			continue;
		}
	}

	if (symtab == NULL || strtab == NULL) {
		/*
		 * No symtab? No strtab? That should not happen here,
		 * and should have been verified during __elfN(loadimage).
		 * This must be some kind of a bug.
		 */
		return (0);
	}

	sym_count = (int)((Elf_Sym *)esym - symtab) / sizeof(Elf_Sym);

	/*
	 * The most efficent way to find a symbol would be to calculate a
	 * hash, find proper bucket and chain, and thus find a symbol.
	 * However, that would involve code duplication (e.g. for hash
	 * function). So we're using simpler and a bit slower way: we're
	 * iterating through symbols, searching for the one which name is
	 * 'equal' to 'fdt_static_dtb'. To speed up the process a little bit,
	 * we are eliminating symbols type of which is not STT_NOTYPE, or(and)
	 * those which binding attribute is not STB_GLOBAL.
	 */
	for (i = 0; i < sym_count; i++) {
		COPYOUT(symtab + i, &sym, sizeof(sym));
		if (ELF_ST_BIND(sym.st_info) != STB_GLOBAL ||
		    ELF_ST_TYPE(sym.st_info) != STT_NOTYPE)
			continue;

		strp = strdupout((vm_offset_t)(strtab + sym.st_name));
		if (strcmp(strp, FDT_STATIC_DTB_SYMBOL) == 0) {
			/* Found a match ! */
			free(strp);
			return ((vm_offset_t)(sym.st_value + offs));
		}
		free(strp);
	}
	return (0);
}
Exemple #13
0
/*
 * Load the information expected by a sparc64 kernel.
 *
 * - The 'boothowto' argument is constructed
 * - The 'bootdev' argument is constructed
 * - The kernel environment is copied into kernel space.
 * - Module metadata are formatted and placed in kernel space.
 */
int
md_load(char *args, vm_offset_t *modulep, vm_offset_t *dtbp)
{
    struct preloaded_file	*kfp;
    struct preloaded_file	*xp;
    struct file_metadata	*md;
    vm_offset_t			kernend;
    vm_offset_t			addr;
    vm_offset_t			envp;
    vm_offset_t			size;
    char			*rootdevname;
    int				howto;

    howto = md_getboothowto(args);
    *dtbp = 0;

    /*
     * 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.
     */
    if ((rootdevname = getenv("rootdev")) == NULL)
        rootdevname = getenv("currdev");
    getrootmount(rootdevname);

    /* 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;
    }
    /* pad to a page boundary */
    addr = roundup(addr, PAGE_SIZE);

    /* copy our environment */
    envp = addr;
    addr = md_copyenv(addr);

    /* pad to a page boundary */
    addr = roundup(addr, PAGE_SIZE);

    kernend = 0;
    kfp = file_findfile(NULL, "elf64 kernel");
    if (kfp == NULL)
        kfp = file_findfile(NULL, "elf kernel");
    if (kfp == NULL)
        panic("can't find kernel file");
    file_addmetadata(kfp, MODINFOMD_HOWTO, sizeof howto, &howto);
    file_addmetadata(kfp, MODINFOMD_ENVP, sizeof envp, &envp);
    file_addmetadata(kfp, MODINFOMD_KERNEND, sizeof kernend, &kernend);
    file_addmetadata(kfp, MODINFOMD_DTLB_SLOTS, sizeof dtlb_slot, &dtlb_slot);
    file_addmetadata(kfp, MODINFOMD_ITLB_SLOTS, sizeof itlb_slot, &itlb_slot);
    file_addmetadata(kfp, MODINFOMD_DTLB,
                     dtlb_slot * sizeof(*dtlb_store), dtlb_store);
    file_addmetadata(kfp, MODINFOMD_ITLB,
                     itlb_slot * sizeof(*itlb_store), itlb_store);

    *modulep = addr;
    size = md_copymodules(0);
    kernend = roundup(addr + size, PAGE_SIZE);

    md = file_findmetadata(kfp, MODINFOMD_KERNEND);
    bcopy(&kernend, md->md_data, sizeof kernend);

    (void)md_copymodules(addr);

    return(0);
}
Exemple #14
0
static int
command_boot(int argc, char *argv[])
{
    struct preloaded_file	*fp;
    char *local_module_path;
    char *exported_module_path;

    /*
     * See if the user has specified an explicit kernel to boot.
     */
    if ((argc > 1) && (argv[1][0] != '-')) {

	/* XXX maybe we should discard everything and start again? */
	if (file_findfile(NULL, NULL) != NULL) {
	    sprintf(command_errbuf, "can't boot '%s', kernel module already loaded", argv[1]);
	    return(CMD_ERROR);
	}

	/* find/load the kernel module */
	if (mod_loadkld(argv[1], argc - 2, argv + 2) != 0)
	    return(CMD_ERROR);
	/* we have consumed all arguments */
	argc = 1;
    }

    /*
     * See if there is a kernel module already loaded
     */
    if (file_findfile(NULL, NULL) == NULL)
	if (loadakernel(0, argc - 1, argv + 1))
	    /* we have consumed all arguments */
	    argc = 1;

    /*
     * Loaded anything yet?
     */
    if ((fp = file_findfile(NULL, NULL)) == NULL) {
	command_errmsg = "no bootable kernel";
	return(CMD_ERROR);
    }

    /*
     * If we were given arguments, discard any previous.
     * XXX should we merge arguments?  Hard to DWIM.
     */
    if (argc > 1) {
	if (fp->f_args != NULL)
	    free(fp->f_args);
	fp->f_args = unargv(argc - 1, argv + 1);
    }

    /* Hook for platform-specific autoloading of modules */
    if (archsw.arch_autoload() != 0)
	return(CMD_ERROR);

    /*
     * Exec the kernel.  We have to shift our exported_module_path
     * (which has the correct /boot prefix for the kernel) over to
     * module_path.  If the exec fails we switch it back.
     */
    exported_module_path = getenv("exported_module_path");
    if (exported_module_path) {
	    exported_module_path = strdup(exported_module_path);
	    local_module_path = getenv("module_path");
	    if (local_module_path)
		local_module_path = strdup(local_module_path);
	    setenv("module_path", exported_module_path, 1);
	    unsetenv("exported_module_path");
    }

    /* Call the exec handler from the loader matching the kernel */
    file_formats[fp->f_loader]->l_exec(fp);

    if (exported_module_path) {
	    if (local_module_path) {
		setenv("module_path", local_module_path, 1);
		free(local_module_path);
	    } else {
		unsetenv("module_path");
	    }
	    setenv("exported_module_path", exported_module_path, 1);
	    free(exported_module_path);
    }
    return(CMD_ERROR);
}
Exemple #15
0
static int
multiboot_exec(struct preloaded_file *fp)
{
	vm_offset_t			 module_start, last_addr, metadata_size;
	vm_offset_t			 modulep, kernend, entry;
	struct file_metadata		*md;
	Elf_Ehdr			*ehdr;
	struct multiboot_info		*mb_info = NULL;
	struct multiboot_mod_list	*mb_mod = NULL;
	char				*cmdline = NULL;
	size_t				 len;
	int				 error, mod_num;

	/*
	 * Don't pass the memory size found by the bootloader, the memory
	 * available to Dom0 will be lower than that.
	 */
	unsetenv("smbios.memory.enabled");

	/* Allocate the multiboot struct and fill the basic details. */
	mb_info = malloc(sizeof(struct multiboot_info));
	if (mb_info == NULL) {
		error = ENOMEM;
		goto error;
	}
	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 = VTOP(mbl_name);

	/* Set the Xen command line. */
	if (fp->f_args == NULL) {
		/* Add the Xen command line if it is set. */
		cmdline = getenv("xen_cmdline");
		if (cmdline != NULL) {
			fp->f_args = strdup(cmdline);
			if (fp->f_args == NULL) {
				error = ENOMEM;
				goto error;
			}
		}
	}
	if (fp->f_args != NULL) {
		len = strlen(fp->f_name) + 1 + strlen(fp->f_args) + 1;
		cmdline = malloc(len);
		if (cmdline == NULL) {
			error = ENOMEM;
			goto error;
		}
		snprintf(cmdline, len, "%s %s", fp->f_name, fp->f_args);
		mb_info->cmdline = VTOP(cmdline);
		mb_info->flags |= MULTIBOOT_INFO_CMDLINE;
	}

	/* Find the entry point of the Xen kernel and save it for later */
	if ((md = file_findmetadata(fp, MODINFOMD_ELFHDR)) == NULL) {
		printf("Unable to find %s entry point\n", fp->f_name);
		error = EINVAL;
		goto error;
	}
	ehdr = (Elf_Ehdr *)&(md->md_data);
	entry = ehdr->e_entry & 0xffffff;

	/*
	 * Prepare the multiboot module list, Xen assumes the first
	 * module is the Dom0 kernel, and the second one is the initramfs.
	 * This is not optimal for FreeBSD, that doesn't have a initramfs
	 * but instead loads modules dynamically and creates the metadata
	 * info on-the-fly.
	 *
	 * As expected, the first multiboot module is going to be the
	 * FreeBSD kernel loaded as a raw file. The second module is going
	 * to contain the metadata info and the loaded modules.
	 *
	 * On native FreeBSD loads all the modules and then places the
	 * metadata info at the end, but this is painful when running on Xen,
	 * because it relocates the second multiboot module wherever it
	 * likes. In order to workaround this limitation the metadata
	 * information is placed at the start of the second module and
	 * the original modulep value is saved together with the other
	 * metadata, so we can relocate everything.
	 *
	 * Native layout:
	 *           fp->f_addr + fp->f_size
	 * +---------+----------------+------------+
	 * |         |                |            |
	 * | Kernel  |    Modules     |  Metadata  |
	 * |         |                |            |
	 * +---------+----------------+------------+
	 * fp->f_addr                 modulep      kernend
	 *
	 * Xen layout:
	 *
	 * Initial:
	 *                      fp->f_addr + fp->f_size
	 * +---------+----------+----------------+------------+
	 * |         |          |                |            |
	 * | Kernel  | Reserved |    Modules     |  Metadata  |
	 * |         |          |                |  dry run   |
	 * +---------+----------+----------------+------------+
	 * fp->f_addr
	 *
	 * After metadata polacement (ie: final):
	 *                                  fp->f_addr + fp->f_size
	 * +-----------+---------+----------+----------------+
	 * |           |         |          |                |
	 * |  Kernel   |  Free   | Metadata |    Modules     |
	 * |           |         |          |                |
	 * +-----------+---------+----------+----------------+
	 * fp->f_addr            modulep                     kernend
	 * \__________/          \__________________________/
	 *  Multiboot module 0    Multiboot module 1
	 */

	fp = file_findfile(NULL, "elf kernel");
	if (fp == NULL) {
		printf("No FreeBSD kernel provided, aborting\n");
		error = EINVAL;
		goto error;
	}

	if (fp->f_metadata != NULL) {
		printf("FreeBSD kernel already contains metadata, aborting\n");
		error = EINVAL;
		goto error;
	}


	mb_mod = malloc(sizeof(struct multiboot_mod_list) * NUM_MODULES);
	if (mb_mod == NULL) {
		error = ENOMEM;
		goto error;
	}

	bzero(mb_mod, sizeof(struct multiboot_mod_list) * NUM_MODULES);

	/*
	 * Calculate how much memory is needed for the metatdata. We did
	 * an approximation of the maximum size when loading the kernel,
	 * but now we know the exact size, so we can release some of this
	 * preallocated memory if not needed.
	 */
	last_addr = roundup(max_addr(), PAGE_SIZE);
	mod_num = num_modules(fp);

	/*
	 * Place the metadata after the last used address in order to
	 * calculate it's size, this will not be used.
	 */
	error = bi_load64(fp->f_args, last_addr, &modulep, &kernend, 0);
	if (error != 0) {
		printf("bi_load64 failed: %d\n", error);
		goto error;
	}
	metadata_size = roundup(kernend - last_addr, PAGE_SIZE);

	/* Check that the size is not greater than what we have reserved */
	if (metadata_size > METADATA_RESV_SIZE(mod_num)) {
		printf("Required memory for metadata is greater than reserved "
		    "space, please increase METADATA_FIXED_SIZE and "
		    "METADATA_MODULE_SIZE and rebuild the loader\n");
		error = ENOMEM;
		goto error;
	}

	/* Clean the metadata added to the kernel in the bi_load64 dry run */
	file_removemetadata(fp);

	/*
	 * This is the position where the second multiboot module
	 * will be placed.
	 */
	module_start = fp->f_addr + fp->f_size - metadata_size;

	error = bi_load64(fp->f_args, module_start, &modulep, &kernend, 0);
	if (error != 0) {
		printf("bi_load64 failed: %d\n", error);
		goto error;
	}

	mb_mod[0].mod_start = fp->f_addr;
	mb_mod[0].mod_end = fp->f_addr + fp->f_size;
	mb_mod[0].mod_end -= METADATA_RESV_SIZE(mod_num);

	mb_mod[1].mod_start = module_start;
	mb_mod[1].mod_end = last_addr;

	mb_info->mods_count = NUM_MODULES;
	mb_info->mods_addr = VTOP(mb_mod);
	mb_info->flags |= MULTIBOOT_INFO_MODS;

	dev_cleanup();
	__exec((void *)VTOP(multiboot_tramp), (void *)entry,
	    (void *)VTOP(mb_info));

	panic("exec returned");

error:
	if (mb_mod)
		free(mb_mod);
	if (mb_info)
		free(mb_info);
	if (cmdline)
		free(cmdline);
	return (error);
}
Exemple #16
0
/*
 * Load the information expected by an i386 kernel.
 *
 * - The 'boothowto' argument is constructed
 * - The 'bootdev' argument is constructed
 * - The 'bootinfo' struct is constructed, and copied into the kernel space.
 * - The kernel environment is copied into kernel space.
 * - Module metadata are formatted and placed in kernel space.
 */
int
bi_load32(char *args, int *howtop, int *bootdevp, vm_offset_t *bip, vm_offset_t *modulep, vm_offset_t *kernendp)
{
    struct preloaded_file	*xp, *kfp;
    struct i386_devdesc		*rootdev;
    struct file_metadata	*md;
    vm_offset_t			addr;
    vm_offset_t			kernend;
    vm_offset_t			envp;
    vm_offset_t			size;
    vm_offset_t			ssym, esym;
    char			*rootdevname;
    int				bootdevnr, i, howto;
    char			*kernelname;
    const char			*kernelpath;

    howto = bi_getboothowto(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");
    i386_getdev((void **)(&rootdev), rootdevname, NULL);
    if (rootdev == NULL) {		/* bad $rootdev/$currdev */
	printf("can't determine root device\n");
	return(EINVAL);
    }

    /* Try reading the /etc/fstab file to select the root device */
    getrootmount(i386_fmtdev(rootdev));

    /* Do legacy rootdev guessing */

    /* XXX - use a default bootdev of 0.  Is this ok??? */
    bootdevnr = 0;

    switch(rootdev->d_type) {
    case DEVT_CD:
	    /* Pass in BIOS device number. */
	    bi.bi_bios_dev = bc_unit2bios(rootdev->d_kind.bioscd.unit);
	    bootdevnr = bc_getdev(rootdev);
	    break;

    case DEVT_DISK:
	/* pass in the BIOS device number of the current disk */
	bi.bi_bios_dev = bd_unit2bios(rootdev->d_kind.biosdisk.unit);
	bootdevnr = bd_getdev(rootdev);
	break;

    case DEVT_NET:
	    break;
	    
    default:
	printf("WARNING - don't know how to boot from device type %d\n", rootdev->d_type);
    }
    if (bootdevnr == -1) {
	printf("root device %s invalid\n", i386_fmtdev(rootdev));
	return (EINVAL);
    }
    free(rootdev);

    /* 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;
    }
    /* pad to a page boundary */
    addr = roundup(addr, PAGE_SIZE);

    /* copy our environment */
    envp = addr;
    addr = bi_copyenv(addr);

    /* pad to a page boundary */
    addr = roundup(addr, PAGE_SIZE);

    kfp = file_findfile(NULL, "elf kernel");
    if (kfp == NULL)
      kfp = file_findfile(NULL, "elf32 kernel");
    if (kfp == NULL)
	panic("can't find kernel file");
    kernend = 0;	/* fill it in later */
    file_addmetadata(kfp, MODINFOMD_HOWTO, sizeof howto, &howto);
    file_addmetadata(kfp, MODINFOMD_ENVP, sizeof envp, &envp);
    file_addmetadata(kfp, MODINFOMD_KERNEND, sizeof kernend, &kernend);
    bios_addsmapdata(kfp);

    /* Figure out the size and location of the metadata */
    *modulep = addr;
    size = bi_copymodules32(0);
    kernend = roundup(addr + size, PAGE_SIZE);
    *kernendp = kernend;

    /* patch MODINFOMD_KERNEND */
    md = file_findmetadata(kfp, MODINFOMD_KERNEND);
    bcopy(&kernend, md->md_data, sizeof kernend);

    /* copy module list and metadata */
    (void)bi_copymodules32(addr);

    ssym = esym = 0;
    md = file_findmetadata(kfp, MODINFOMD_SSYM);
    if (md != NULL)
	ssym = *((vm_offset_t *)&(md->md_data));
    md = file_findmetadata(kfp, MODINFOMD_ESYM);
    if (md != NULL)
	esym = *((vm_offset_t *)&(md->md_data));
    if (ssym == 0 || esym == 0)
	ssym = esym = 0;		/* sanity */

    /* legacy bootinfo structure */
    kernelname = getenv("kernelname");
    i386_getdev(NULL, kernelname, &kernelpath);
    bi.bi_version = BOOTINFO_VERSION;
    bi.bi_kernelname = 0;		/* XXX char * -> kernel name */
    bi.bi_nfs_diskless = 0;		/* struct nfs_diskless * */
    bi.bi_n_bios_used = 0;		/* XXX would have to hook biosdisk driver for these */
    for (i = 0; i < N_BIOS_GEOM; i++)
        bi.bi_bios_geom[i] = bd_getbigeom(i);
    bi.bi_size = sizeof(bi);
    bi.bi_memsizes_valid = 1;
    bi.bi_basemem = bios_basemem / 1024;
    bi.bi_extmem = bios_extmem / 1024;
    bi.bi_envp = envp;
    bi.bi_modulep = *modulep;
    bi.bi_kernend = kernend;
    bi.bi_kernelname = VTOP(kernelpath);
    bi.bi_symtab = ssym;       /* XXX this is only the primary kernel symtab */
    bi.bi_esymtab = esym;

    /* legacy boot arguments */
    *howtop = howto | RB_BOOTINFO;
    *bootdevp = bootdevnr;
    *bip = VTOP(&bi);

    return(0);
}
Exemple #17
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);
}
Exemple #18
0
static int
command_load(int argc, char *argv[])
{
    char	*typestr;
    int		dofile, dokld, ch, error;
    
    dokld = dofile = 0;
    optind = 1;
    optreset = 1;
    typestr = NULL;
    if (argc == 1) {
	command_errmsg = "no filename specified";
	return (CMD_CRIT);
    }
    while ((ch = getopt(argc, argv, "kt:")) != -1) {
	switch(ch) {
	case 'k':
	    dokld = 1;
	    break;
	case 't':
	    typestr = optarg;
	    dofile = 1;
	    break;
	case '?':
	default:
	    /* getopt has already reported an error */
	    return (CMD_OK);
	}
    }
    argv += (optind - 1);
    argc -= (optind - 1);

    printf("Loading %s...\n", argv[1]);
    /*
     * Request to load a raw file?
     */
    if (dofile) {
	if ((typestr == NULL) || (*typestr == 0)) {
	    command_errmsg = "invalid load type";
	    return (CMD_CRIT);
	}

	if (file_findfile(argv[1], typestr) != NULL) {
		snprintf(command_errbuf, sizeof (command_errbuf),
		    "warning: file '%s' already loaded", argv[1]);
		return (CMD_WARN);
	}

	if (file_loadraw(argv[1], typestr, argc - 2, argv + 2, 1) != NULL)
		return (CMD_OK);

	/* Failing to load mfs_root is never going to end well! */
	if (strcmp("mfs_root", typestr) == 0)
		return (CMD_FATAL);

	return (CMD_ERROR);
    }
    /*
     * Do we have explicit KLD load ?
     */
    if (dokld || file_havepath(argv[1])) {
	error = mod_loadkld(argv[1], argc - 2, argv + 2);
	if (error == EEXIST) {
	    snprintf(command_errbuf, sizeof (command_errbuf),
		"warning: KLD '%s' already loaded", argv[1]);
	    return (CMD_WARN);
	}
	
	return (error == 0 ? CMD_OK : CMD_CRIT);
    }
    /*
     * Looks like a request for a module.
     */
    error = mod_load(argv[1], NULL, argc - 2, argv + 2);
    if (error == EEXIST) {
	snprintf(command_errbuf, sizeof (command_errbuf),
	    "warning: module '%s' already loaded", argv[1]);
	return (CMD_WARN);
    }

    return (error == 0 ? CMD_OK : CMD_CRIT);
}
Exemple #19
0
/*
 * Attempt to load the file (file) as an ELF module.  It will be stored at
 * (dest), and a pointer to a module structure describing the loaded object
 * will be saved in (result).
 */
int
__elfN(loadfile)(char *filename, u_int64_t dest, struct preloaded_file **result)
{
    struct preloaded_file	*fp, *kfp;
    struct elf_file		ef;
    Elf_Ehdr 			*ehdr;
    int				err;
    ssize_t			bytes_read;

    fp = NULL;
    bzero(&ef, sizeof(struct elf_file));

    /*
     * Open the image, read and validate the ELF header 
     */
    if (filename == NULL)	/* can't handle nameless */
	return(EFTYPE);
    if ((ef.fd = open(filename, O_RDONLY)) == -1)
	return(errno);
    ef.firstpage = malloc(PAGE_SIZE);
    if (ef.firstpage == NULL) {
	close(ef.fd);
	return(ENOMEM);
    }
    bytes_read = read(ef.fd, ef.firstpage, PAGE_SIZE);
    ef.firstlen = (size_t)bytes_read;
    if (bytes_read < 0 || ef.firstlen <= sizeof(Elf_Ehdr)) {
	err = EFTYPE;		/* could be EIO, but may be small file */
	goto oerr;
    }
    ehdr = ef.ehdr = (Elf_Ehdr *)ef.firstpage;

    /* Is it ELF? */
    if (!IS_ELF(*ehdr)) {
	err = EFTYPE;
	goto oerr;
    }
    if (ehdr->e_ident[EI_CLASS] != ELF_TARG_CLASS ||	/* Layout ? */
	ehdr->e_ident[EI_DATA] != ELF_TARG_DATA ||
	ehdr->e_ident[EI_VERSION] != EV_CURRENT ||	/* Version ? */
	ehdr->e_version != EV_CURRENT ||
	ehdr->e_machine != ELF_TARG_MACH) {		/* Machine ? */
	err = EFTYPE;
	goto oerr;
    }


    /*
     * Check to see what sort of module we are.
     */
    kfp = file_findfile(NULL, NULL);
    if (ehdr->e_type == ET_DYN) {
	/* Looks like a kld module */
	if (kfp == NULL) {
	    printf("elf" __XSTRING(__ELF_WORD_SIZE) "_loadfile: can't load module before kernel\n");
	    err = EPERM;
	    goto oerr;
	}
	if (strcmp(__elfN(kerneltype), kfp->f_type)) {
	    printf("elf" __XSTRING(__ELF_WORD_SIZE) "_loadfile: can't load module with kernel type '%s'\n", kfp->f_type);
	    err = EPERM;
	    goto oerr;
	}
	/* Looks OK, got ahead */
	ef.kernel = 0;

    } else if (ehdr->e_type == ET_EXEC) {
	/* Looks like a kernel */
	if (kfp != NULL) {
	    printf("elf" __XSTRING(__ELF_WORD_SIZE) "_loadfile: kernel already loaded\n");
	    err = EPERM;
	    goto oerr;
	}
	/* 
	 * Calculate destination address based on kernel entrypoint 	
	 */
	dest = (ehdr->e_entry & ~PAGE_MASK);
	if (dest == 0) {
	    printf("elf" __XSTRING(__ELF_WORD_SIZE) "_loadfile: not a kernel (maybe static binary?)\n");
	    err = EPERM;
	    goto oerr;
	}
	ef.kernel = 1;

    } else {
	err = EFTYPE;
	goto oerr;
    }

    if (archsw.arch_loadaddr != NULL)
	dest = archsw.arch_loadaddr(LOAD_ELF, ehdr, dest);
    else
	dest = roundup(dest, PAGE_SIZE);

    /* 
     * Ok, we think we should handle this.
     */
    fp = file_alloc();
    if (fp == NULL) {
	    printf("elf" __XSTRING(__ELF_WORD_SIZE) "_loadfile: cannot allocate module info\n");
	    err = EPERM;
	    goto out;
    }
    if (ef.kernel)
	setenv("kernelname", filename, 1);
    fp->f_name = strdup(filename);
    fp->f_type = strdup(ef.kernel ? __elfN(kerneltype) : __elfN(moduletype));

#ifdef ELF_VERBOSE
    if (ef.kernel)
	printf("%s entry at 0x%jx\n", filename, (uintmax_t)ehdr->e_entry);
#else
    printf("%s ", filename);
#endif

    fp->f_size = __elfN(loadimage)(fp, &ef, dest);
    if (fp->f_size == 0 || fp->f_addr == 0)
	goto ioerr;

    /* save exec header as metadata */
    file_addmetadata(fp, MODINFOMD_ELFHDR, sizeof(*ehdr), ehdr);

    /* Load OK, return module pointer */
    *result = (struct preloaded_file *)fp;
    err = 0;
    goto out;
    
 ioerr:
    err = EIO;
 oerr:
    file_discard(fp);
 out:
    if (ef.firstpage)
	free(ef.firstpage);
    close(ef.fd);
    return(err);
}
Exemple #20
0
static vm_offset_t
fdt_find_static_dtb()
{
	Elf_Ehdr *ehdr;
	Elf_Shdr *shdr;
	Elf_Sym sym;
	vm_offset_t strtab, symtab, fdt_start;
	uint64_t offs;
	struct preloaded_file *kfp;
	struct file_metadata *md;
	char *strp;
	int i, sym_count;

	debugf("fdt_find_static_dtb()\n");

	sym_count = symtab = strtab = 0;
	strp = NULL;

	offs = __elfN(relocation_offset);

	kfp = file_findfile(NULL, NULL);
	if (kfp == NULL)
		return (0);

	/* Locate the dynamic symbols and strtab. */
	md = file_findmetadata(kfp, MODINFOMD_ELFHDR);
	if (md == NULL)
		return (0);
	ehdr = (Elf_Ehdr *)md->md_data;

	md = file_findmetadata(kfp, MODINFOMD_SHDR);
	if (md == NULL)
		return (0);
	shdr = (Elf_Shdr *)md->md_data;

	for (i = 0; i < ehdr->e_shnum; ++i) {
		if (shdr[i].sh_type == SHT_DYNSYM && symtab == 0) {
			symtab = shdr[i].sh_addr + offs;
			sym_count = shdr[i].sh_size / sizeof(Elf_Sym);
		} else if (shdr[i].sh_type == SHT_STRTAB && strtab == 0) {
			strtab = shdr[i].sh_addr + offs;
		}
	}

	/*
	 * The most efficent way to find a symbol would be to calculate a
	 * hash, find proper bucket and chain, and thus find a symbol.
	 * However, that would involve code duplication (e.g. for hash
	 * function). So we're using simpler and a bit slower way: we're
	 * iterating through symbols, searching for the one which name is
	 * 'equal' to 'fdt_static_dtb'. To speed up the process a little bit,
	 * we are eliminating symbols type of which is not STT_NOTYPE, or(and)
	 * those which binding attribute is not STB_GLOBAL.
	 */
	fdt_start = 0;
	while (sym_count > 0 && fdt_start == 0) {
		COPYOUT(symtab, &sym, sizeof(sym));
		symtab += sizeof(sym);
		--sym_count;
		if (ELF_ST_BIND(sym.st_info) != STB_GLOBAL ||
		    ELF_ST_TYPE(sym.st_info) != STT_NOTYPE)
			continue;
		strp = strdupout(strtab + sym.st_name);
		if (strcmp(strp, FDT_STATIC_DTB_SYMBOL) == 0)
			fdt_start = (vm_offset_t)sym.st_value + offs;
		free(strp);
	}
	return (fdt_start);
}
/*
 * Attempt to load the file (file) as an ELF module.  It will be stored at
 * (dest), and a pointer to a module structure describing the loaded object
 * will be saved in (result).
 */
int
__elfN(obj_loadfile)(char *filename, u_int64_t dest,
    struct preloaded_file **result)
{
	struct preloaded_file *fp, *kfp;
	struct elf_file	ef;
	Elf_Ehdr *hdr;
	int err;
	ssize_t bytes_read;

	fp = NULL;
	bzero(&ef, sizeof(struct elf_file));

	/*
	 * Open the image, read and validate the ELF header
	 */
	if (filename == NULL)	/* can't handle nameless */
		return(EFTYPE);
	if ((ef.fd = open(filename, O_RDONLY)) == -1)
		return(errno);

	hdr = &ef.hdr;
	bytes_read = read(ef.fd, hdr, sizeof(*hdr));
	if (bytes_read != sizeof(*hdr)) {
		err = EFTYPE;	/* could be EIO, but may be small file */
		goto oerr;
	}

	/* Is it ELF? */
	if (!IS_ELF(*hdr)) {
		err = EFTYPE;
		goto oerr;
	}
	if (hdr->e_ident[EI_CLASS] != ELF_TARG_CLASS ||	/* Layout ? */
	    hdr->e_ident[EI_DATA] != ELF_TARG_DATA ||
	    hdr->e_ident[EI_VERSION] != EV_CURRENT ||	/* Version ? */
	    hdr->e_version != EV_CURRENT ||
	    hdr->e_machine != ELF_TARG_MACH ||		/* Machine ? */
	    hdr->e_type != ET_REL) {
		err = EFTYPE;
		goto oerr;
	}

	if (hdr->e_shnum * hdr->e_shentsize == 0 || hdr->e_shoff == 0 ||
	    hdr->e_shentsize != sizeof(Elf_Shdr)) {
		err = EFTYPE;
		goto oerr;
	}

	kfp = file_findfile(NULL, NULL);
	if (kfp == NULL) {
		printf("elf" __XSTRING(__ELF_WORD_SIZE)
		    "_obj_loadfile: can't load module before kernel\n");
		err = EPERM;
		goto oerr;
	}
	if (strcmp(__elfN(obj_kerneltype), kfp->f_type)) {
		printf("elf" __XSTRING(__ELF_WORD_SIZE)
		    "_obj_loadfile: can't load module with kernel type '%s'\n",
		    kfp->f_type);
		err = EPERM;
		goto oerr;
	}

	if (archsw.arch_loadaddr != NULL)
		dest = archsw.arch_loadaddr(LOAD_ELF, hdr, dest);
	else
		dest = roundup(dest, PAGE_SIZE);

	/*
	 * Ok, we think we should handle this.
	 */
	fp = file_alloc();
	if (fp == NULL) {
		printf("elf" __XSTRING(__ELF_WORD_SIZE)
		    "_obj_loadfile: cannot allocate module info\n");
		err = EPERM;
		goto out;
	}
	fp->f_name = strdup(filename);
	fp->f_type = strdup(__elfN(obj_moduletype));

	printf("%s ", filename);

	fp->f_size = __elfN(obj_loadimage)(fp, &ef, dest);
	if (fp->f_size == 0 || fp->f_addr == 0)
		goto ioerr;

	/* save exec header as metadata */
	file_addmetadata(fp, MODINFOMD_ELFHDR, sizeof(*hdr), hdr);

	/* Load OK, return module pointer */
	*result = (struct preloaded_file *)fp;
	err = 0;
	goto out;

ioerr:
	err = EIO;
oerr:
	file_discard(fp);
out:
	close(ef.fd);
	if (ef.e_shdr != NULL)
		free(ef.e_shdr);

	return(err);
}
Exemple #22
0
static int
multiboot_obj_loadfile(char *filename, u_int64_t dest,
    struct preloaded_file **result)
{
	struct preloaded_file	*mfp, *kfp, *rfp;
	int			 error, mod_num;

	/* See if there's a aout multiboot kernel loaded */
	mfp = file_findfile(NULL, "aout multiboot kernel");
	if (mfp != NULL) {
		/* we have normal kernel loaded, add module */
		rfp = file_loadraw(filename, "module", 0, NULL, 0);
		if (rfp == NULL) {
			printf(
			"Unable to load %s as a multiboot payload module\n",
			filename);
			return (EINVAL);
		}
		rfp->f_size = roundup(rfp->f_size, PAGE_SIZE);
		*result = rfp;
		return (0);
	}

	/* See if there's a multiboot kernel loaded */
	mfp = file_findfile(NULL, "elf multiboot kernel");
	if (mfp == NULL) {
		return (EFTYPE);	/* this allows to check other methods */
	}

	/*
	 * We have a multiboot kernel loaded, see if there's a
	 * kernel loaded also.
	 */
	kfp = file_findfile(NULL, "elf kernel");
	if (kfp == NULL) {
		/*
		 * No kernel loaded, this must be it. The kernel has to
		 * be loaded as a raw file, it will be processed by
		 * Xen and correctly loaded as an ELF file.
		 */
		rfp = file_loadraw(filename, "elf kernel", 0, NULL, 0);
		if (rfp == NULL) {
			printf(
			"Unable to load %s as a multiboot payload kernel\n",
			filename);
			return (EINVAL);
		}

		/* Load kernel metadata... */
		setenv("kernelname", filename, 1);
		error = elf64_load_modmetadata(rfp, rfp->f_addr + rfp->f_size);
		if (error) {
			printf("Unable to load kernel %s metadata error: %d\n",
			    rfp->f_name, error);
			return (EINVAL);
		}

		/*
		 * Save space at the end of the kernel in order to place
		 * the metadata information. We do an approximation of the
		 * max metadata size, this is not optimal but it's probably
		 * the best we can do at this point. Once all modules are
		 * loaded and the size of the metadata is known this
		 * space will be recovered if not used.
		 */
		mod_num = num_modules(rfp);
		rfp->f_size = roundup(rfp->f_size, PAGE_SIZE);
		rfp->f_size += METADATA_RESV_SIZE(mod_num);
		*result = rfp;
	} else {
		/* The rest should be loaded as regular modules */
		error = elf64_obj_loadfile(filename, dest, result);
		if (error != 0) {
			printf("Unable to load %s as an object file, error: %d",
			    filename, error);
			return (error);
		}
	}

	return (0);
}
Exemple #23
0
/*
 * Load the information expected by a powerpc kernel.
 *
 * - The 'boothowto' argument is constructed
 * - The 'bootdev' argument is constructed
 * - The kernel environment is copied into kernel space.
 * - Module metadata are formatted and placed in kernel space.
 */
int
md_load_dual(char *args, vm_offset_t *modulep, vm_offset_t *dtb, int kern64)
{
    struct preloaded_file	*kfp;
    struct preloaded_file	*xp;
    struct file_metadata	*md;
    vm_offset_t			kernend;
    vm_offset_t			addr;
    vm_offset_t			envp;
    vm_offset_t			fdtp;
    vm_offset_t			size;
    uint64_t			scratch64;
    char			*rootdevname;
    int				howto;

    align = kern64 ? 8 : 4;
    howto = md_getboothowto(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");
    if (rootdevname == NULL)
	    rootdevname = getenv("currdev");
    /* Try reading the /etc/fstab file to select the root device */
    getrootmount(rootdevname);

    /* 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;
    }
    /* pad to a page boundary */
    addr = roundup(addr, PAGE_SIZE);

    /* copy our environment */
    envp = addr;
    addr = md_copyenv(addr);

    /* pad to a page boundary */
    addr = roundup(addr, PAGE_SIZE);

    /* Copy out FDT */
    size = fdt_copy(addr);
    *dtb = fdtp = addr;
    addr = roundup(addr + size, PAGE_SIZE);

    kernend = 0;
    kfp = file_findfile(NULL, kern64 ? "elf64 kernel" : "elf32 kernel");
    if (kfp == NULL)
	kfp = file_findfile(NULL, "elf kernel");
    if (kfp == NULL)
	panic("can't find kernel file");
    file_addmetadata(kfp, MODINFOMD_HOWTO, sizeof howto, &howto);
    if (kern64) {
	scratch64 = envp;
	file_addmetadata(kfp, MODINFOMD_ENVP, sizeof scratch64, &scratch64);
	scratch64 = fdtp;
	file_addmetadata(kfp, MODINFOMD_DTBP, sizeof scratch64, &scratch64);
	scratch64 = kernend;
	file_addmetadata(kfp, MODINFOMD_KERNEND, sizeof scratch64, &scratch64);
    } else {
	file_addmetadata(kfp, MODINFOMD_ENVP, sizeof envp, &envp);
	file_addmetadata(kfp, MODINFOMD_DTBP, sizeof fdtp, &fdtp);
	file_addmetadata(kfp, MODINFOMD_KERNEND, sizeof kernend, &kernend);
    }

    *modulep = addr;
    size = md_copymodules(0, kern64);
    kernend = roundup(addr + size, PAGE_SIZE);

    md = file_findmetadata(kfp, MODINFOMD_KERNEND);
    if (kern64) {
	scratch64 = kernend;
	bcopy(&scratch64, md->md_data, sizeof scratch64);
    } else {
	bcopy(&kernend, md->md_data, sizeof kernend);
    }
	
    (void)md_copymodules(addr, kern64);

    return(0);
}
Exemple #24
0
static int
multiboot_loadfile(char *filename, u_int64_t dest,
    struct preloaded_file **result)
{
	uint32_t		*magic;
	int			 i, error;
	caddr_t			 header_search;
	ssize_t			 search_size;
	int			 fd;
	struct multiboot_header	*header;
	struct preloaded_file	*fp;

	if (filename == NULL)
		return (EFTYPE);

	/* is kernel already loaded? */
	fp = file_findfile(NULL, NULL);
	if (fp != NULL) {
		return (EFTYPE);
	}

	if ((fd = open(filename, O_RDONLY)) == -1)
		return (errno);

	/*
	 * Read MULTIBOOT_SEARCH size in order to search for the
	 * multiboot magic header.
	 */
	header_search = malloc(MULTIBOOT_SEARCH);
	if (header_search == NULL) {
		close(fd);
		return (ENOMEM);
	}

	search_size = read(fd, header_search, MULTIBOOT_SEARCH);
	magic = (uint32_t *)header_search;

	header = NULL;
	for (i = 0; i < (search_size / sizeof(uint32_t)); i++) {
		if (magic[i] == MULTIBOOT_HEADER_MAGIC) {
			header = (struct multiboot_header *)&magic[i];
			break;
		}
	}

	if (header == NULL) {
		error = EFTYPE;
		goto out;
	}

	/* Valid multiboot header has been found, validate checksum */
	if (header->magic + header->flags + header->checksum != 0) {
		printf(
	"Multiboot checksum failed, magic: 0x%x flags: 0x%x checksum: 0x%x\n",
	header->magic, header->flags, header->checksum);
		error = EFTYPE;
		goto out;
	}

	if ((header->flags & ~MULTIBOOT_SUPPORTED_FLAGS) != 0) {
		printf("Unsupported multiboot flags found: 0x%x\n",
		    header->flags);
		error = EFTYPE;
		goto out;
	}
	/* AOUT KLUDGE means we just load entire flat file as blob */
	if (header->flags & MULTIBOOT_AOUT_KLUDGE) {
		vm_offset_t laddr;
		int got;

		dest = header->load_addr;
		if (lseek(fd, 0, SEEK_SET) == -1) {
			printf("lseek failed\n");
			error = EIO;
			goto out;
		}
		laddr = dest;
		for (;;) {
			got = archsw.arch_readin(fd, laddr, 4096);
			if (got == 0)
				break;
			if (got < 0) {
				printf("error reading: %s", strerror(errno));
				error = EIO;
				goto out;
			}
			laddr += got;
		}

		fp = file_alloc();
		if (fp == NULL) {
			error = ENOMEM;
			goto out;
		}
		fp->f_name = strdup(filename);
		fp->f_type = strdup("aout multiboot kernel");
		fp->f_addr = header->entry_addr;
		fp->f_size = laddr - dest;
		if (fp->f_size == 0) {
			file_discard(fp);
			error = EIO;
			goto out;
		}
		fp->f_metadata = NULL;
		error = 0;
	} else {
		error = elf32_loadfile_raw(filename, dest, &fp, 1);
		if (error != 0) {
			printf("elf32_loadfile_raw failed: %d unable to "
			    "load multiboot kernel\n", error);
			goto out;
		}
	}

	setenv("kernelname", fp->f_name, 1);
	bios_addsmapdata(fp);
	*result = fp;
out:
	free(header_search);
	close(fd);
	return (error);
}
Exemple #25
0
/*
 * Load the information expected by an amd64 kernel.
 *
 * - The 'boothowto' argument is constructed
 * - The 'bootdev' argument is constructed
 * - The 'bootinfo' struct is constructed, and copied into the kernel space.
 * - The kernel environment is copied into kernel space.
 * - Module metadata are formatted and placed in kernel space.
 */
int
bi_load64(char *args, vm_offset_t *modulep, vm_offset_t *kernendp)
{
    struct preloaded_file	*xp, *kfp;
    struct userboot_devdesc	*rootdev;
    struct file_metadata	*md;
    vm_offset_t			addr;
    u_int64_t			kernend;
    u_int64_t			envp;
    vm_offset_t			size;
    char			*rootdevname;
    int				howto;

    if (!bi_checkcpu()) {
	printf("CPU doesn't support long mode\n");
	return (EINVAL);
    }

    howto = bi_getboothowto(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");
    userboot_getdev((void **)(&rootdev), rootdevname, NULL);
    if (rootdev == NULL) {		/* bad $rootdev/$currdev */
	printf("can't determine root device\n");
	return(EINVAL);
    }

    /* Try reading the /etc/fstab file to select the root device */
    getrootmount(userboot_fmtdev((void *)rootdev));

    /* 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;
    }
    /* pad to a page boundary */
    addr = roundup(addr, PAGE_SIZE);

    /* copy our environment */
    envp = addr;
    addr = bi_copyenv(addr);

    /* pad to a page boundary */
    addr = roundup(addr, PAGE_SIZE);

    kfp = file_findfile(NULL, "elf kernel");
    if (kfp == NULL)
      kfp = file_findfile(NULL, "elf64 kernel");
    if (kfp == NULL)
	panic("can't find kernel file");
    kernend = 0;	/* fill it in later */
    file_addmetadata(kfp, MODINFOMD_HOWTO, sizeof howto, &howto);
    file_addmetadata(kfp, MODINFOMD_ENVP, sizeof envp, &envp);
    file_addmetadata(kfp, MODINFOMD_KERNEND, sizeof kernend, &kernend);
    bios_addsmapdata(kfp);

    /* Figure out the size and location of the metadata */
    *modulep = addr;
    size = bi_copymodules64(0);
    kernend = roundup(addr + size, PAGE_SIZE);
    *kernendp = kernend;

    /* patch MODINFOMD_KERNEND */
    md = file_findmetadata(kfp, MODINFOMD_KERNEND);
    bcopy(&kernend, md->md_data, sizeof kernend);

    /* copy module list and metadata */
    (void)bi_copymodules64(addr);

    return(0);
}
Exemple #26
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
bi_load(struct bootinfo *bi, struct preloaded_file *fp, UINTN *mapkey,
    UINTN pages)
{
    char			*rootdevname;
    struct efi_devdesc		*rootdev;
    struct preloaded_file	*xp;
    vaddr_t			addr, bootinfo_addr;
    vaddr_t			ssym, esym;
    struct file_metadata	*md;
    EFI_STATUS			status;
    UINTN			bisz, key;

    /*
     * Version 1 bootinfo.
     */
    bi->bi_magic = BOOTINFO_MAGIC;
    bi->bi_version = 1;

    /*
     * Calculate boothowto.
     */
    bi->bi_boothowto = bi_getboothowto(fp->f_args);

    /*
     * Stash EFI System Table.
     */
    bi->bi_systab = (u_int64_t) ST;

    /* 
     * 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");
    efi_getdev((void **)(&rootdev), rootdevname, NULL);
    if (rootdev == NULL) {		/* bad $rootdev/$currdev */
	printf("can't determine root device\n");
	return(EINVAL);
    }

    /* Try reading the /etc/fstab file to select the root device */
    getrootmount(efi_fmtdev((void *)rootdev));
    free(rootdev);

    ssym = esym = 0;

    ssym = fp->marks[MARK_SYM];
    esym = fp->marks[MARK_END];

    if (ssym == 0 || esym == 0)
	ssym = esym = 0;		/* sanity */

    bi->bi_symtab = ssym;
    bi->bi_esymtab = esym;

    bi->bi_hcdp = (uint64_t)efi_get_table(&hcdp); /* DIG64 HCDP table addr. */
    fpswa_init(&bi->bi_fpswa);		/* find FPSWA interface */

    /* 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;
    }

    /* pad to a page boundary */
    addr = (addr + PAGE_MASK) & ~PAGE_MASK;

    /* copy our environment */
    bi->bi_envp = addr;
    addr = bi_copyenv(addr);

    /* pad to a page boundary */
    addr = (addr + PAGE_MASK) & ~PAGE_MASK;

    /* all done copying stuff in, save end of loaded object space */
    bi->bi_kernend = addr;

    /*
     * Read the memory map and stash it after bootinfo. Align the memory map
     * on a 16-byte boundary (the bootinfo block is page aligned).
     */
    bisz = (sizeof(struct bootinfo) + 0x0f) & ~0x0f;
    bi->bi_memmap = ((u_int64_t)bi) + bisz;
    bi->bi_memmap_size = EFI_PAGE_SIZE * pages - bisz;
    status = BS->GetMemoryMap(&bi->bi_memmap_size,
		(EFI_MEMORY_DESCRIPTOR *)bi->bi_memmap, &key,
		&bi->bi_memdesc_size, &bi->bi_memdesc_version);
    if (EFI_ERROR(status)) {
	printf("bi_load: Can't read memory map\n");
	return EINVAL;
    }
    *mapkey = key;

    return(0);
}
Exemple #27
0
/*
 * Load the information expected by an alpha kernel.
 *
 * - The kernel environment is copied into kernel space.
 * - Module metadata are formatted and placed in kernel space.
 */
int
bi_load(struct bootinfo *bi, struct preloaded_file *fp, char *args)
{
    char			*rootdevname;
    struct ski_devdesc		*rootdev;
    struct preloaded_file	*xp;
    vm_offset_t			addr, bootinfo_addr;
    u_int			pad;
    char			*kernelname;
    vm_offset_t			ssym, esym;
    struct file_metadata	*md;
    EFI_MEMORY_DESCRIPTOR	*memp;

    /*
     * Version 1 bootinfo.
     */
    bi->bi_magic = BOOTINFO_MAGIC;
    bi->bi_version = 1;

    /*
     * Calculate boothowto.
     */
    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");
    ski_getdev((void **)(&rootdev), rootdevname, NULL);
    if (rootdev == NULL) {		/* bad $rootdev/$currdev */
	printf("can't determine root device\n");
	return(EINVAL);
    }

    /* Try reading the /etc/fstab file to select the root device */
    getrootmount(ski_fmtdev((void *)rootdev));
    free(rootdev);

    ssym = esym = 0;
    if ((md = file_findmetadata(fp, MODINFOMD_SSYM)) != NULL)
	ssym = *((vm_offset_t *)&(md->md_data));
    if ((md = file_findmetadata(fp, MODINFOMD_ESYM)) != NULL)
	esym = *((vm_offset_t *)&(md->md_data));
    if (ssym == 0 || esym == 0)
	ssym = esym = 0;		/* sanity */

    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;
    }
    /* pad to a page boundary */
    pad = (u_int)addr & PAGE_MASK;
    if (pad != 0) {
	pad = PAGE_SIZE - pad;
	addr += pad;
    }

    /* copy our environment */
    bi->bi_envp = addr;
    addr = bi_copyenv(addr);

    /* pad to a page boundary */
    pad = (u_int)addr & PAGE_MASK;
    if (pad != 0) {
	pad = PAGE_SIZE - pad;
	addr += pad;
    }
    /* copy module list and metadata */
    bi->bi_modulep = addr;
    addr = bi_copymodules(addr);

    /* all done copying stuff in, save end of loaded object space */
    bi->bi_kernend = addr;

    /* Describe the SKI memory map. */
    bi->bi_memmap = (u_int64_t)(bi + 1);
    bi->bi_memmap_size = 2 * sizeof(EFI_MEMORY_DESCRIPTOR);
    bi->bi_memdesc_size = sizeof(EFI_MEMORY_DESCRIPTOR);
    bi->bi_memdesc_version = 1;

    memp = (EFI_MEMORY_DESCRIPTOR *) bi->bi_memmap;

    memp[0].Type = EfiConventionalMemory;
    memp[0].PhysicalStart = 2L*1024*1024;
    memp[0].VirtualStart = 0;
    memp[0].NumberOfPages = (64L*1024*1024)>>12;
    memp[0].Attribute = EFI_MEMORY_WB;

    memp[1].Type = EfiMemoryMappedIOPortSpace;
    memp[1].PhysicalStart = 0xffffc000000;
    memp[1].VirtualStart = 0;
    memp[1].NumberOfPages = (64L*1024*1024)>>12;
    memp[1].Attribute = EFI_MEMORY_UC;

    return(0);
}
Exemple #28
0
int
__elfN(loadfile_raw)(char *filename, u_int64_t dest,
    struct preloaded_file **result, int multiboot)
{
    struct preloaded_file	*fp, *kfp;
    struct elf_file		ef;
    Elf_Ehdr 			*ehdr;
    int				err;

    fp = NULL;
    bzero(&ef, sizeof(struct elf_file));
    ef.fd = -1;

    err = __elfN(load_elf_header)(filename, &ef);
    if (err != 0)
    	return (err);

    ehdr = ef.ehdr;

    /*
     * Check to see what sort of module we are.
     */
    kfp = file_findfile(NULL, __elfN(kerneltype));
#ifdef __powerpc__
    /*
     * Kernels can be ET_DYN, so just assume the first loaded object is the
     * kernel. This assumption will be checked later.
     */
    if (kfp == NULL)
        ef.kernel = 1;
#endif
    if (ef.kernel || ehdr->e_type == ET_EXEC) {
	/* Looks like a kernel */
	if (kfp != NULL) {
	    printf("elf" __XSTRING(__ELF_WORD_SIZE) "_loadfile: kernel already loaded\n");
	    err = EPERM;
	    goto oerr;
	}
	/* 
	 * Calculate destination address based on kernel entrypoint.
	 *
	 * For ARM, the destination address is independent of any values in the
	 * elf header (an ARM kernel can be loaded at any 2MB boundary), so we
	 * leave dest set to the value calculated by archsw.arch_loadaddr() and
	 * passed in to this function.
	 */
#ifndef __arm__
        if (ehdr->e_type == ET_EXEC)
	    dest = (ehdr->e_entry & ~PAGE_MASK);
#endif
	if ((ehdr->e_entry & ~PAGE_MASK) == 0) {
	    printf("elf" __XSTRING(__ELF_WORD_SIZE) "_loadfile: not a kernel (maybe static binary?)\n");
	    err = EPERM;
	    goto oerr;
	}
	ef.kernel = 1;

    } else if (ehdr->e_type == ET_DYN) {
	/* Looks like a kld module */
	if (multiboot != 0) {
		printf("elf" __XSTRING(__ELF_WORD_SIZE) "_loadfile: can't load module as multiboot\n");
		err = EPERM;
		goto oerr;
	}
	if (kfp == NULL) {
	    printf("elf" __XSTRING(__ELF_WORD_SIZE) "_loadfile: can't load module before kernel\n");
	    err = EPERM;
	    goto oerr;
	}
	if (strcmp(__elfN(kerneltype), kfp->f_type)) {
	    printf("elf" __XSTRING(__ELF_WORD_SIZE) "_loadfile: can't load module with kernel type '%s'\n", kfp->f_type);
	    err = EPERM;
	    goto oerr;
	}
	/* Looks OK, got ahead */
	ef.kernel = 0;

    } else {
	err = EFTYPE;
	goto oerr;
    }

    if (archsw.arch_loadaddr != NULL)
	dest = archsw.arch_loadaddr(LOAD_ELF, ehdr, dest);
    else
	dest = roundup(dest, PAGE_SIZE);

    /* 
     * Ok, we think we should handle this.
     */
    fp = file_alloc();
    if (fp == NULL) {
	    printf("elf" __XSTRING(__ELF_WORD_SIZE) "_loadfile: cannot allocate module info\n");
	    err = EPERM;
	    goto out;
    }
    if (ef.kernel == 1 && multiboot == 0)
	setenv("kernelname", filename, 1);
    fp->f_name = strdup(filename);
    if (multiboot == 0)
    	fp->f_type = strdup(ef.kernel ?
    	    __elfN(kerneltype) : __elfN(moduletype));
    else
    	fp->f_type = strdup("elf multiboot kernel");

#ifdef ELF_VERBOSE
    if (ef.kernel)
	printf("%s entry at 0x%jx\n", filename, (uintmax_t)ehdr->e_entry);
#else
    printf("%s ", filename);
#endif

    fp->f_size = __elfN(loadimage)(fp, &ef, dest);
    if (fp->f_size == 0 || fp->f_addr == 0)
	goto ioerr;

    /* save exec header as metadata */
    file_addmetadata(fp, MODINFOMD_ELFHDR, sizeof(*ehdr), ehdr);

    /* Load OK, return module pointer */
    *result = (struct preloaded_file *)fp;
    err = 0;
    goto out;
    
 ioerr:
    err = EIO;
 oerr:
    file_discard(fp);
 out:
    if (ef.firstpage)
	free(ef.firstpage);
    if (ef.fd != -1)
    	close(ef.fd);
    return(err);
}
Exemple #29
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
bi_load(struct preloaded_file *fp, uint64_t *bi_addr)
{
	struct bootinfo bi;
	struct preloaded_file *xp;
	struct file_metadata *md;
	struct devdesc *rootdev;
	char *rootdevname;
	vm_offset_t addr, ssym, esym;

	bzero(&bi, sizeof(struct bootinfo));
	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");
	i386_getdev((void**)&rootdev, rootdevname, NULL);
	if (rootdev != NULL) {
		/* Try reading /etc/fstab to select the root device. */
		getrootmount(i386_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 + PAGE_MASK) & ~PAGE_MASK;
	bi.bi_kernend = addr;

	return (ldr_bootinfo(&bi, bi_addr));
}
Exemple #30
0
/*
 * Load the information expected by a kernel.
 *
 * - The 'boothowto' argument is constructed
 * - The 'bootdev' argument is constructed
 * - The kernel environment is copied into kernel space.
 * - Module metadata are formatted and placed in kernel space.
 */
int
md_load(char *args, vm_offset_t *modulep)
{
	struct preloaded_file	*kfp, *bfp;
	struct preloaded_file	*xp;
	struct file_metadata	*md;
	struct bootinfo		*bip;
	vm_offset_t		kernend;
	vm_offset_t		addr;
	vm_offset_t		envp;
	vm_offset_t		size;
	vm_offset_t		vaddr;
	vm_offset_t		dtbp;
	char			*rootdevname;
	int			howto;
	int			i;

	/*
	 * These metadata addreses must be converted for kernel after
	 * relocation.
	 */
	uint32_t		mdt[] = {
	    MODINFOMD_SSYM, MODINFOMD_ESYM, MODINFOMD_KERNEND,
	    MODINFOMD_ENVP,
#if defined(LOADER_FDT_SUPPORT)
	    MODINFOMD_DTBP
#endif
	};

	howto = md_getboothowto(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");
	if (rootdevname == NULL)
		rootdevname = getenv("currdev");
	/* Try reading the /etc/fstab file to select the root device */
	getrootmount(rootdevname);

	/* 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;
	}
	/* Pad to a page boundary */
	addr = roundup(addr, PAGE_SIZE);

	/* Copy our environment */
	envp = addr;
	addr = md_copyenv(addr);

	/* Pad to a page boundary */
	addr = roundup(addr, PAGE_SIZE);

	kernend = 0;
	kfp = file_findfile(NULL, "elf32 kernel");
	if (kfp == NULL)
		kfp = file_findfile(NULL, "elf kernel");
	if (kfp == NULL)
		panic("can't find kernel file");
	file_addmetadata(kfp, MODINFOMD_HOWTO, sizeof howto, &howto);
	file_addmetadata(kfp, MODINFOMD_ENVP, sizeof envp, &envp);

#if defined(LOADER_FDT_SUPPORT)
	/* Handle device tree blob */
	dtbp = fdt_fixup();
	if (dtbp != 0)
		file_addmetadata(kfp, MODINFOMD_DTBP, sizeof dtbp, &dtbp);
	else
		pager_output("WARNING! Trying to fire up the kernel, but no "
		    "device tree blob found!\n");
#endif

	file_addmetadata(kfp, MODINFOMD_KERNEND, sizeof kernend, &kernend);

	/* Figure out the size and location of the metadata */
	*modulep = addr;
	size = md_copymodules(0);
	kernend = roundup(addr + size, PAGE_SIZE);

	/* Provide MODINFOMD_KERNEND */
	md = file_findmetadata(kfp, MODINFOMD_KERNEND);
	bcopy(&kernend, md->md_data, sizeof kernend);

	/* Convert addresses to the final VA */
	*modulep -= __elfN(relocation_offset);

	for (i = 0; i < sizeof mdt / sizeof mdt[0]; i++) {
		md = file_findmetadata(kfp, mdt[i]);
		if (md) {
			bcopy(md->md_data, &vaddr, sizeof vaddr);
			vaddr -= __elfN(relocation_offset);
			bcopy(&vaddr, md->md_data, sizeof vaddr);
		}
	}

	/* Only now copy actual modules and metadata */
	(void)md_copymodules(addr);

	return (0);
}